🍎 ViewController Life Cycle
-
보통 앱을 만들 때, 단일 스크린 위에서 여러 개의 뷰 컨트롤러들로 화면전환이 가능한 앱을 만듭니다.
-
앱이 복잡해질수록 컨트롤러들을 잘 관리해줘야 하는데, 알맞은 타이밍에 내가 원하는 코드를 작성하는 것이 중요합니다.
-
이를 위해서 뷰컨트롤러 라이프싸이클을 이해해야하고, 잘 이해하지않은 채로 다음 프로젝트들을 진행하다보면 막히는 부분이 있을 수 있으니 진도를 잠깐 스탑하고 내용을 정리해보겠습니다.
🍏 Life Cycle관련 메서드들.
- UIViewController의 객체에는 뷰 객체를 관리하는 메서드들이 정의되있습니다.
- 이 메서드들은 각자 자신들이 불러져야하는 타이밍일 때 ios의 시스템에 의해 자동으로 호출이 됩니다.
- UIViewController의 하위 클래스를 생성할 때, UIViewController에 정의된 이 메서드들을 override하여 라이프 싸이클의 상황에 맞게 적절한 로직들을 메서드에 추가할 수 있습니다.
🧃 viewDidLoad()
뷰 컨트롤러의 모든 뷰들이 메모리에 로드됐을 때 호출
그래서 메모리에 처음 로드될 때 한 번만 호출
보통 라이프싸이클 내에서 딱 한번 호출될 행위들을 이 메소드 안에 정의함.
뷰와 관련된 추가적인 초기화 작업, 네트워크 호출과 같은 일회성작업을 정의함.
🧃 viewWillAppear()
뷰가 뷰 계층에 추가되고, 화면에 보이기 직전에 매 번 호출
무슨 뜻이냐면 다른 뷰로 이동했다가 돌아오면 재호출
뷰와 관련된 추가적인 초기화 작업을 정의함.
🧃 viewDidAppear()
뷰 컨트롤러의 뷰가 뷰 계층에 추가된 후 호출됨.
보통 뷰를 나타낼 때 필요한 추가작업이나 애니메이션을 시작하는 작업을 정의할 때 사용. (viewWillAppear() 메서드에 애니메이션을 넣으면 안되겠죠~?! 뷰가 나타나기 전에 애니메이션 수행하면 정작 뷰 나타날 때는 애니메이션이 안보입니다.)
🧃 viewWillDisappear()
뷰 컨트롤러의 뷰가 뷰 계층에서 사라지기 전에 호출됨.
보통 뷰가 생성된 뒤 작업한 내용을 되돌리는 작업 혹은
최종적으로 데이터를 저장하는 작업을 정의함.
🧃 viewDidDisappear()
뷰 컨트롤러의 뷰가 뷰 계층에서 사라진 뒤에 호출됨.
뷰가 사라지는 것과 관련된 추가 작업을 여기에 정의함.
🍏 실제 코드예시를 보며 살피기!
- 지금부터 실제 예시를 통해 살펴보겠습니다.
- NavigationController에서의 화면전환을 예로 가져와보겠습니다.
설명을 위해 위와 같이 스토리보드를 구성하였습니다.
그리고 각 ViewController에는 위와 같이 메서드를 정의하여 화면전환상황마다 어떤 메서드가 호출이 되는지 살펴보았습니다.
🧃 RootViewController <-> CodePushViewController
- 네, 네비게이션컨트롤러의 루트뷰가 로드되었습니다. 그리고 뷰가 나타날 것이고, 나타났다는 메서드가 실행이 되었습니다.
- 그럼 이제 CodePush버튼을 눌러서 CodePushViewController로 화면을 전환해보겠습니다.
- 새로운 뷰컨트롤러의 뷰가 메모리에 로드되었고, 루트뷰는 사라졌습니다.
- 이때 잘 보시면, 루트뷰가 사라질 예정 -> 코드뷰가 나타날 예정 -> 루트 뷰 사라짐 -> 코드뷰 나타남 순으로 진행되는 것을 보실 수 있습니다.
- 그럼 다시 back버튼을 눌러서 이전 rootView화면으로 돌아가보겠습니다.
- 자, 화면이 전환되었네요. 여기서 눈여겨보아야할 것이 있습니다.
- "rootViewController의 뷰가 '로드'되었다."라는 말을 출력하는 viewDidLoad() 메서드는 호출되지 않았단 것입니다. 여기서 주목할 점은 NavigationController의 Stack형식입니다.
- 화면이 전환되면서 루트뷰의 뷰는 사라졌지만 루트뷰의 데이터는 여전히 Stack에 Push되어있던 상황입니다. 메모리에서 해제된 상태는 아니었던 것입니다. 단순히 우리는 코드뷰에서 Pop을 통해 돌아온 것이고, 루트뷰는 처음 앱을 실행할 때 이미 로드되었으니, viewDidLoad() 메서드는 다시 호출되지 않습니다.
- 그럼 다시 한번 더 버튼을 눌러 CodeViewController로 화면전환을 해보겠습니다.
-
이제 눈치채셨을것이라 생각합니다. 이전에 루트뷰로 돌아왔을 때 코드뷰는 Pop을 통해 Stack을 빠져나갔으니, 다시 코드뷰 화면으로 전환할 때는 새로 메모리에 Push되면서 viewDidLoad() 메서드도 호출된 것입니다.
-
이제 viewDidLoad() 라는 메서드를 좀 더 명확하게 이해할 수 있습니다. 앱 실행 후 단순히 딱 한 번만 호출된다는 의미라기보단 메모리에 없었던 것이 새로 호출되었을 때 로드되며 실행되는 메서드라고 이해하면 될 것 같습니다.
-
만약 코드뷰에서 한번 더 푸시하여 제가 위의 스토리보드에서 지정한 CodePushPush화면으로 이동했다가 돌아온다면 코드뷰의 viewDidLoad()메서드는 호출되지 않습니다.
🧃 RootViewController <-> CodePresentViewController
- 자 이번에는 앱을 다시 실행하고 Present를 통해 ViewController 위에 다른 ViewController를 호출해보겠습니다.
- 처음 루트뷰가 로드되는 것은 이제 당연하구요.
- CodePresent 버튼을 눌러 CodePresentViewController 뷰로 화면을 호출해보겠습니다.
- 뭔가 허전하지않나요? 맞습니다. 루트뷰가 사라지지않았습니다. 루트뷰는 여전히 '나타나있는' 상태이고, 그 위에 새로운 뷰가 나타나고 사라지기만 하였습니다.
- 이는 현재 Present Modally 형태로 프레젠트뷰가 호출되었기 때문입니다.
- 잘 보시면, 이전 화면이 완전히 덮혀있는 상태가 아닙니다. 그렇기 때문에 루트뷰가 사라지지않은 것이죠.
- 하지만 Presentation속성을 Full Screen으로 바꿔주면 완전히 덮이면서 루트뷰도 사라진 것으로 인식되어 루트뷰가 사라졌다는 메서드가 호출되게됩니다.
오늘의 정리는 여기까지입니다. 수정할 사항이나 추가할 사항이 있다면 앞으로의 공부를 통해 추가하겠습니다. 감사합니다.