View Life Cycle

이원희·2020년 11월 24일
4

📱 iOS

목록 보기
2/24
post-thumbnail

오늘은 iOS View Life Cycle에 대해서 알아보려 한다.
Android를 공부할 때도 처음에는 Life Cycle에 대해서 배우는데 그때 이리저리 로그를 꽂아서 어떤 순서로 동작하는지 공부했던 게 생각나서 오늘은 그렇게 공부해보려 한다.

Android든 iOS든 생명 주기에 대해서는 다들 중요하게 다루는 데는 이유가 있다.
뭐 사실 나는 기본을 그렇게 중요하게 쌓았던 개발자는 아니라서...
(엄청나게 고생도 하고 필요성을 많이 느껴서 지금이라도 쌓기 위해 노력 중...)
처음에 생명 주기에 대해서 보면

그래그래 이렇게 동작하는 거 알겠어! 근데 어쩌라고?

라는 느낌이다.
프로젝트가 복잡하지 않으면 생명 주기를 고려하지 않고도 프로그램이 잘 돌아갈 수 있다.
내가 겪었던 여러 상황에 대해서 말하자면

  • 짧은 애니메이션이 사용자에게 보이지 않음 혹은 애니메이션의 중간부터 보게됨
  • 다른 view에 갔다 다시 올 때 자꾸 view가 초기화됨

등등과 같은 여러 상황을 겪었었다. (예시보다 복잡한 상황들도 있었음...)
그때는 생명주기에 대해서 다시 차분하게 짚고 넘어가야 하는 시기라는 걸 무시하고 임시방편으로 잘 고쳐 나갔었다.

이젠 다시는 그런 일을 겪고 싶지도 않고, 잘 알고 싶어 정리하는 포스팅이다.

그렇다면 View의 Life Cycle이 뭔데?

이름에서 알 수 있듯 View가 생기고 사라지는거에 대한 주기이다.

View Life Cycle에 대해 공부하면 위와 같은 그림을 볼 수 있다.
위의 그림으로 하나씩 주기를 살펴보자
(init은 나중에 따로 다뤄보고)

로그를 통해 생명 주기에 대해서 알아보기로 했으니 아래의 사진처럼 각각의 주기에 해당하는 Method에 print로 로그를 꽂았다.
프로젝트를 실행하면
다음과 같은 로그가 찍히는걸 확인할 수 있다.

loadView

위의 로그에서 loadView가 가장 먼저 호출됨을 확인했다.
그렇다면 loadView의 역할은 무엇일까?
loadView는 viewController 관리하는 View를 만드는 역할을 한다.
(ViewController에 대해서도 포스팅해야겠다...)

loadView는 viewController의 view 프로퍼티가 현재 nil일때 호출된다.
호출된 loadView는 view를 로드하거나 생성하고 생성된 view를 viewController의 view 프로터피에 지정한다.
outlet들과 action들이 이 Method에서 생성되고 연결된다.

내가 위에
view 프로퍼티에 지정한다.
라고 썼는데 view 프로퍼티를 통해

view.backgroundColor = UIColor.blue

위와 같은 코드를 사용할 수 있게된다.
(이 코드는 두번째 view의 background를 바꿔주는 코드)


(와우... 색깔 선정... 무슨 일이야...)

사진 설명

1: '이동' 버튼으로 첫번째 화면에서 두번째 화면으로 이동
2: Back 버튼으로 두번째 화면에서 첫번째 화면으로 이동
3: '이동' 버튼으로 첫번째 화면에서 두번째 화면으로 이동

우선 위의 사진을 통해 유추할 수 있는건

  • 첫번째 화면에 NavigationBar가 있으니 첫번째 화면은 UINavigationController로 이뤄져 있다.
  • 이 게시물에서 UINavigationController는 Stack으로 구성되어 있다고 했다.

loadView()로 사진 이해하기

  • 프로젝트를 실행하면 "1. 첫번째" 화면을 볼 수 있다.
    -> 첫번째 viewController의 view 프로퍼티가 nil이므로 1. 첫번재 viewController의 loadView()가 호출된다.
  • "1. 첫번째" 화면에서 "이동"버튼을 눌러 "2. 두번째" 화면으로 이동한다.
    -> 두번째 viewController의 view 프로퍼티가 nil이므로 2. 두번째 viewController의 loadView()가 호출된다.
    -> 생성된 viewController는 Navigation stack에 push된다.
  • "2. 두번째" 화면에서 Back을 누르면 "1. 첫번째" 화면이 보인다.
    -> 두번째 viewController가 Navigation stack에서 pop된다.
    -> 두번째 viewController가 메모리에서 해제되어 deinit 로그가 찍혔다.
    -> 첫번째 viewController는 아직 메모리에서 해제되지 않았으므로 loadView() 로그가 찍히지 않는다.
  • "1. 첫번째" 화면에서 "이동"버튼을 눌러 "2. 두번째" 화면으로 이동한다.
    -> 두번째 viewController가 완전히 메모리에서 해제된 이후이므로 다시 두번째 viewController의 loadView()가 호출된다.

If you use Interface Builder to create your views and initialize the view controller, you must not override this method.
(출처: https://developer.apple.com/documentation/uikit/uiviewcontroller/1621454-loadview)

라고 Apple 문서에 써져 있다.
storyboard나 .xib 파일로 만들어지는 경우가 아닌 직접적으로 코딩하여 view를 만드는 경우를 제외하고서는 loadView를 override하지 않는 것이 좋다고한다.


위의 코드는 loadView를 override해서 view를 직접 만들어주는 코드이다.
위의 코드처럼 직접 코딩해서 view를 만드는 경우는 override하지 말라는 것이다.

loadView만 써도 벌써 이만큼... 오늘도 간단하게 쓰고 넘어가려했는데... 왜 나는 그것이 안되는가...

viewDidLoad

viewDidLoad가 생명 주기에서 가장 익숙한 Method가 아닐까 싶다.

Called after the controller's view is loaded into memory.
(출처: https://developer.apple.com/documentation/uikit/uiviewcontroller/1621495-viewdidload)

라고 Apple 문서에 써져 있다.
viewController의 view가 메모리에 로드된 직후에 호출되는 Method다.

즉, loadView에서는 view를 생성하고 구성해 메모리에 올리는 거고,
viewDidLoad는 view가 메모리에 올라간 직후에 호출되는 것이다.

view에 추가적인 작업을 하고 싶다면 이 Method에서 하면 된다.

viewWillAppear, viewDidAppear

viewWillAppear

Notifies the view controller that its view is about to be added to a view hierarchy.
(출처: https://developer.apple.com/documentation/uikit/uiviewcontroller/1621510-viewwillappear)

라고 Apple 문서에 써져 있다.
(view hierarchy 부분은 나중에 다룰거니 일단은 이런게 있구나 하면 될거 같다..)

viewWillAppear(_:)view가 이제 화면에 나타날거라고(Notifies) 알려주는 Method이다.
즉, view가 화면에 나타나기 직전에 호출된다.
(viewDidLoad가 호출된다고 화면에 view가 보이는 것이 아니다.)

view가 화면에 어떻게 보여질지 보여지기 전에 추가할 수 있다.

viewDidAppear

viewDidAppear는 이름에서 알 수 있듯 view가 화면에 나타났다고 알려주는 Method이다.
(애니메이션을 시작하거나 비디오나 음악을 재생할 수 있다.)

viewWillDisappear, viewDidDisappear

viewWillDisappear

viewWillDisappear(_:)는 view가 사라지기 직전에 호출되는 Method이다.
(여기서 키보드를 숨기는 것과 같은 처리를 할 수 있다.)

viewDidDisappear

view가 사라진 직후에 호출되는 Method이다.
(여기서 notification을 듣는거를 멈출 수 있다.)

마무리

우리는 view의 Life Cycle에 대해서 알아봤다.


위의 사진에서 다른 점을 찾은 사람!🙋‍♀️
왼쪽에서는

  • "2. 두번째" 화면으로 이동할때 "1. 첫번째" viewController에서 viewWillDisappear, viewDidDisappear가 호출된다.
  • Back 버튼으로 "1. 첫번쨰" 화면으로 다시 돌아올 때 "1. 첫번째" viewController에서 viewWillAppear, viewDidAppear가 호출된다.

오른쪽에서는

  • "2. 두번째" 화면으로 이동할때 "1. 첫번째" viewController에서 viewWillDisappear, viewDidDisappear가 호출되지 않는다.
  • Back 버튼으로 "1. 첫번쨰" 화면으로 다시 돌아올 때 "1. 첫번째" viewController에서 viewWillAppear, viewDidAppear가 호출되지 않는다.

왼쪽은 Navigation 방식으로 "2. 두번째" 화면을 호출했을때의 로그이고, (아래 사진에서 왼쪽)
오른쪽은 modal 방식(fullScreen이 아닌)으로 "2. 두번째" 화면을 호출했을때의 로그이다. (아래 사진에서 오른쪽)

위의 사진에서 보면 왼쪽에서는 "1. 첫번쨰" view가 화면에서 보이지 않는다.
하지만 오른쪽에서는 "1. 첫번째" view가 "2. 두번째" view 뒤에 조금 보이고 있다.

즉, 우리에게 보여지는 화면에서 view가 보이는지 안 보이는지에 따라 viewWillDisappear, viewDidDisappear가 호출된다.

그럼 내가 위에서 언급한 경험들에 대해서 얘기해보자

  • 짧은 애니메이션이 사용자에게 보이지 않음 혹은 애니메이션의 중간부터 보게됨
  • 다른 view에 갔다 다시 올 때 자꾸 view가 초기화됨

1. 짧은 애니메이션이 사용자에게 보이지 않음 혹은 애니메이션의 중간부터 보게됨

왜 이런 일이 생겼을까?
viewDidLoad()에서 애니메이션이 실행되도록 코드를 짰기 때문이다.

viewDidLoad()는 view가 메모리에 로드되었을때 호출되는 Method이다.
그러므로 viewDidLoad()가 호출되었다고 해당 view가 사용자에게 보이는 것이 아니다.

그래서 짧은 애니메이션을 viewDidLoad()에서 실행하면 화면에 해당 view가 보여지게 되는 동안 애니메이션이 끝나버리게 된다.

2. 다른 view에 갔다 다시 올 때 자꾸 view가 초기화됨

이 부분은 다양한 이유가 있을 수 있는데 다른 view로 이동했다 돌아올때 appear Method들이 다시 호출되므로 이 부분에 대해서 적절한 조치가 취해지지 않아서 그랬다.

View Life Cycle은 이쯤에서 마무리해야겠다.
오늘도 간단하게 포스팅하려 했지만 길어진 포스팅...
하지만 아직... 다룰게 많다...ㅋㅋㅋ
언제나처럼 틀린 부분 지적과 궁금한 부분은 언제든 환영합니다.👋

0개의 댓글