안녕하세요. 개발하는 정주입니다.
오늘은 "UIViewController 생명주기(Life Cycle)"에 대해 알아보겠습니다.
마지막에는 프로젝트를 생성해 생명주기 메서드 호출을 알아보겠습니다.
생명주기 흐름도
생명주기 흐름도를 먼저 보도록 하겠습니다.
UIViewController의 생명주기는 위 흐름도대로 진행됩니다.
메서드 이름에 view가 들어간 것은 진하게 표시하였습니다.
하나하나 살펴보도록 합시다.
0. init
init 과정은 storyboard나 코드로 view controller를 생성하는 과정입니다.
UIViewController의 생명주기로 말하기엔 애매하고 생명주기에 들어서기 전 단계가 더 정확하겠네요.
1. loadView
loadView는 컨트롤러가 관리하는 view를 생성하고 Heap 메모리에 load 합니다.
UIViewController의 view가 생성되는 단계로 말할 수도 있습니다.
2022.05.17 - [🍎 iOS/iOS 개발] - [iOS] ViewController에서 View 분리하기
위 글에서는 loadView( )를 사용하는 코드를 볼 수 있습니다.
loadView( )에서 UIViewController의 view가 생성되므로 직접 만든 UIView를 loadView( )에서 바꿔치기(?) 한 것입니다.
공식 문서에는 "You should never call this method directly."라고 명시되어 있습니다.
이것을 보고 "override도 하면 안 되는 거 아니야?"라고 생각할 수 있지만 그건 아니고
self.loadView( )처럼 직접 호출만 하지 말라는 의미입니다.
(You can override this method in order to create your views manually.라고 적혀 있네요.)
loadView에서 만들고 메모리에 올린 후 viewDidLoad( )가 호출됩니다.
2. viewDidLoad
UIViewController를 새로 생성하면 기본으로 들어가 있는 메서드로 가장 익숙한 생명주기 메서드이죠?
viewDidLoad( )는 view가 메모리에 올라간 뒤 시스템에 의해 자동으로 호출됩니다.
메서드 이름에서도 loadView -> viewDidLoad로 load가 된 뒤 호출되는 것이라고 알 수 있습니다.
viewDidLoad( )는 메모리 경고로 viewDidUnload가 호출되지 않는 이상
view가 만들어질 때 한 번만 호출되고 재호출되지 않습니다.
그래서 리소스를 초기화하거나 view의 초기화 작업을 주로 이곳에서 합니다.
viewDidLoad( )는 한 번만 호출되므로 view가 보일 때마다 해야 하는 작업은 다른 곳에 해주어야겠죠?
3. viewWillAppear
view가 나타나기 직전에 호출되는 메서드입니다.
viewWillAppear( ), viewDidAppear( )는 viewDidLoad( )와 혼동할 수 있는데요.
viewDidLoad( )는 view의 생성이라면 viewXXXAppear( )는 view가 보일 때 호출된다고 말할 수 있습니다.
그래서 viewXXXAppear( )는 view가 화면에 보일 때마다 매번 호출됩니다.
"view가 보일 때마다 호출된다"가 무슨 말인가요?
ViewController -> NextViewController -> Back키 클릭 -> ViewController 시나리오라고 가정해 봅시다.
두 번째에서는 viewDidLoad( )는 호출되지 않고 viewWillAppear( )만 호출되는 것을 볼 수 있습니다.
왜냐하면 NextViewController로 이동할 때 ViewController는 가려지고 Back키를 눌렀을 때 ViewController가 다시 "보이기" 때문입니다.
이제 view가 보일 때마다 호출된다는 것의 의미를 아시겠죠?
4. viewDidAppear
viewDidAppear( )는 view가 화면에 나타난 직후에 호출됩니다.
view가 화면에 나타났다는 것을 컨트롤러에게 알리는 역할입니다.
하나의 UIViewController에서는 viewWillAppear -> viewDidAppear 순서로 호출됩니다.
두 개의 ViewController간 이동하는 과정에서 어떨지는 마지막에 살펴봅시다.
5. viewWillDisappear
view가 뷰 계층에서 사라지기 직전 호출됩니다.
컨트롤러에게 view가 사라질 예정이라는 것을 알리는 역할입니다.
뷰를 생성한 뒤 했던 작업을 되돌릴 때, 변경사항 또는 기타 상태를 저장할 때 viewWillDisappear( )를 override 하여 사용하면 됩니다.
6. viewDidDisappear
view가 뷰 계층에서 완전히 사라졌을 때 호출됩니다.
실험해보니 사람 눈으로 봤을 때 뷰가 사라진 후 즉각 호출되진 않고 내부적으로 뷰가 완전히 사라진 뒤에 호출됩니다.
사용 시 주의하셔야 할 듯 하네요.
+. didReceiveMemoryWarning
시스템이 사용 가능한 메모리가 부족해지면 ViewController에게 메모리가 부족하다는 메시지를 보냅니다.
이때 didReceiveMemoryWarning( )이 호출됩니다.
이 메서드를 override 하여 ViewController에서 사용하는 추가 메모리를 해제할 수 있습니다.
단! 개발자가 메모리가 부족할 것 같다고 스스로 self.didReceiveMemoryWarning( )을 호출하면 안 됩니다.
시스템이 판단하여 호출해줄 것입니다.
직접 해보자(Navigation)
직접 생명주기 메서드를 호출하면서 확인해보겠습니다.
NavigationController를 이용해 FirstVC와 SecondVC를 이동하며 테스트해보았습니다.
1. FirstVC 생성
앱을 실행한 뒤 FirstVC가 처음 생겼을 때 호출되는 메서드입니다.
위에서 공부했던 대로
loadView -> viewDidLoad 순서로 호출되고 viewWIllAppear -> viewDidAppear이 호출되었습니다.
2. SecondVC로 이동
Next 버튼을 눌러 FirstVC에서 SecondVC로 이동할 때 호출되는 메서드입니다.
여기서 주의 깊게 살펴봐야 할 점은 Will과 Did의 순서입니다.
viewWillDisappear -> viewWillAppear -> viewDidDisappear -> viewDidAppear 순서로 호출되는 것이 흥미로웠습니다.
SecondVC가 loadView -> viewDidLoad까지 호출됩니다.
그 뒤로 FirstVC의 viewWillDisappear가 호출되고 SecondVC의 viewWillAppear가 호출됩니다.
마지막으로 FirstVC의 viewDidDisappear가 호출되고 SecondVC의 viewDidAppear가 호출됩니다.
새로운 ViewController를 보여줄 때 새로운 VC를 보여주고 기존 VC를 사라지게 하는 것이 아니라,
기존의 VC를 없애고 새로운 VC를 보여준다는 것을 알 수 있습니다.
3. Back버튼을 눌러 FirstVC로 이동
Back버튼을 눌러 FirstVC로 다시 이동했을 때 호출되는 메서드입니다.
이번에도 마찬가지로 Disappear -> Appear 순서로 호출이 되었습니다.
FirstVC의 loadView, viewDidLoad는 호출되지 않는 모습도 볼 수 있습니다.
직접 해보자(Modal)
Modal은 Navigation과 살짝 다릅니다.
저렇게 기존 화면이 살짝 보이는 형태인 게 포인트입니다.
1. FirstVC 생성
내비게이션과 동일하여 생략합니다.
2. SecondVC 띄우기
Next 버튼을 이용해 SecondVC를 Modal로 띄웠을 때 호출되는 메서드입니다.
내비게이션 방법과 무슨 차이점이 있는지 눈치채셨나요?
FirstVC의 viewWillDisappear와 viewDidDisappear가 호출되지 않습니다.
어떻게 보면 이해가 되는 것이 뒤에 살짝쿵 보이잖아요?
그래서 사라지는 것은 아니므로 호출이 안 되겠구나 생각할 수 있습니다.
아무튼, 모달 방식에서는 FirstVC의 viewWillDisappear와 viewDidDisappear가 호출되지 않는다는 것이 중요합니다.
3. SecondVC 없애기
SecondVC Modal을 없앴을 때 호출되는 메서드입니다.
FirstVC의 viewWillDisappear와 viewDidDisappear가 호출되지 않았기 때문에
당연히 Appear 메서드들도 호출되지 않습니다.
따라서 SecondVC의 Disappear 메서드들만 호출됩니다.
마무리
오늘은 ViewController의 생명주기에 대해 알아보았습니다.
생각보다 많은 생명주기 메서드들로 세분화되어 있는데
메서드명을 잘 지어서 이름만으로 역할을 알 수 있다는 것이 인상 깊었습니다.
이것이 네이밍이 중요한 이유인가 봅니다.
다음에는 앱의 생명주기에 대해 알아보도록 하겠습니다.
감사합니다!
참고
https://developer.apple.com/documentation/uikit/uiviewcontroller
https://zeddios.tistory.com/43
아직은 초보 개발자입니다.
더 효율적인 코드 훈수 환영합니다!
공감과 댓글 부탁드립니다.