본문 바로가기
IOS App Programming/트러블 슈팅

네비게이션 스택과 모달 시트에서의 뷰 컨트롤러 라이프 사이

by B_Tori 2024. 1. 11.

라이프 사이클 기본 정리

https://zeddios.tistory.com/43

라이프 사이클의 기본적인 내용은 이 블로그를 참고해 공부했다.

추가적으로 네비게이션 스택에서의 라이프 사이클 호출 방법과 모달 시트로 뷰를 연결하였을 때 라이프 사이클에 차이가 있어 정리를 해보았음

뷰 컨트롤러 연결 상태

 

일단 뷰 컨트롤러의 모습을 살펴보면 위와 같이 1번 뷰에서 버튼을 누르면 2번 뷰, Sheet뷰로 이동할 수 있으며

2번 뷰는 네비게이션을, Sheet뷰는 modal present로 연결

1번 뷰를 띄웠을 때

그냥 뷰 한개를 띄울 때는 예상했던 순서대로 didLoad - willAppear - DidAppear 가 호출된다.

2번 뷰 네비게이션 이동

1) 1번 뷰에서 2번 뷰로 이동했을 때

2번 뷰의 didLoad - 1번 뷰 will disappear - 2번 뷰 will appear - 1번 뷰 did disappear - 2번 뷰 did appear 순서로 호출된다.

2) 2번 뷰에서 다시 1번 뷰를 이동할 때 (돌아올 때)

비슷한 순서이지만 1번 뷰의 didload는 호출되지 않는다.

didload는 화면이 처음 만들어질 때 한 번만 실행되는 함수로 초기 설정을 담당한다고 하였다.

 

3) 그 상태에서 다시 2번 뷰로 다시 넘어간다면 didLoad는 호출이 안될까?

1번과 다르게 2번뷰의 didload가 실행되었다.

이는 네비게이션 스택과 관련이 있다.

네비게이션으로 연결된 컨트롤러들은 네비게이션 스택 안에 순서대로 차곡차곡 쌓이게 된다.

즉 스택 가장 하단에 루트뷰 컨트롤러가 있고 그 위에 다른 컨트롤러들이 push 되는 형태이다.

그리고 뒤로가게 되면 해당 컨트롤러 (스택 가장 상단에 위치한 컨트롤러)가 사라지면서 스택에서 pop 되는 구조이다.

여기서 중요한 점은 스택에서 pop된 컨트롤러는 메모리에서 사라지게 된다.

viewDidLoad의 설명을 다시 한번 짚어보면

viewDidLoad : 뷰가 메모리에 로드되고 난 뒤 호출

 

2번 뷰에서 뒤로가기 하는 순간 메모리에서 사라졌기 때문에 다시 2번 뷰를 호출하게 되면 메모리에 새로 로드되면서 viewDidLoad가 실행되는 것이다.

따라서 루트 뷰 컨트롤러인 1번 뷰는 계속해서 스택에 남아있어 메모리가 해제되지 않아 viewDidLoad가 처음 한 번만 실행되었지만

2번 뷰 컨트롤러의 경우 뒤로가기 할 때마다 스택에서 pop 되어 메모리가 해제되기 때문에 다시 호출하면 메모리에 새롭게 로드되어 didload가 계속 실행되는 것이었다.

modal sheet 호출

그렇다면 이제 modalSheet로 호출한 sheetViewController를 살펴보자.

예전에 프로젝트를 진행하면서 시트 형태의 모달로 뷰 컨트롤러를 띄우고 이전 뷰 컨트롤러가 사라질 때 disappear를 통해 특정 작업을 진행하려고 했었는데 실패를 했던 경험이 있다.

 

sheet를 올렸을 때와 내렸을 때의 실행 결과이다.

네비게이션과 다르게 sheet를 호출한 1번 뷰가 disappear 되지 않고 시트의 라이프 사이클만 호출되는 걸 확인할 수 있다.

 

iOS 13 이후의 기본 스타일은 fullScreen → automatic이다.

automatic 스타일은 모달을 페이지 시트 형태로 만든다.

시트 형태로 모달을 올릴 경우 기존 뷰 컨트롤러와 독립적으로 생명주기가 작동하여 1번 뷰에서는 전혀 영향이 없던 것이었다.

 

따라서 prsent로 뷰를 연결했을 시 기존 뷰에서 사라지기 전에 해야 할 작업이 있다면 해결 방법은

가장 쉬운 방법으로

- modalPresentationStyle을 fullScreen 형태로 연결

이처럼 1번 뷰의 생명주기도 작동하는 것을 볼 수 있다.

 

- 대리자 형태의 무언가를 사용하여 전달해 주는 방법

 

위에 언급했던 실패 경험에서는 원래 원하던 디자인이 시트 디자인이었기 때문에 간단한 풀스크린 방법은 사용하지 못했고

RxSwift를 이용하여 데이터를 바인딩하여 해결해 주었다.

댓글