UIViewController

봄이아빠·2024년 12월 3일
3

UIKit

목록 보기
2/5

UIViewController

뷰 컨트롤러는 뷰의 계층도를 관리해주는 오브젝트로
다음과 같은 주로 다음과 같은 책임을 지는 객체입니다.

  • 사용자와 상호작용하여 반응함.
  • 뷰의 콘텐츠를 업데이트하고 아래에 깔린 데이터를 업데이트함.
  • 앱의 다른 오브젝트와 상호작용
  • 뷰의 크기를 조정하거나 전체 인터페이스의 레이아웃을 조정함

해당 객체를 바로 선언하여 사용하는 일은 드물고 주로 UIViewController를 상속하고 필요한 메서드를 재정의하거나 메서드와 프로퍼티 등을 추가하여 사용합니다.

또한 뷰 컨트롤러는 자신만의 뷰 세트를 갖게 됩니다.
여기서 중요한 점은 뷰 컨트롤러는 뷰와 서브뷰의 유일한 소유자여야 한다는 것입니다.
따라서 생성과 소멸주기도 해당 뷰 컨트롤러에게 관리할 책임이 있습니다.

스토리보드 등으로 뷰를 요청한다면 UIKit이 자동으로 해당 뷰 컨트롤러를 위한 뷰 객체를 생성하지만 코드로 직접 뷰를 생성하는 경우는 사용자가 주의를 기울여야 합니다.

만일 여러 뷰 컨트롤러가 동일한 뷰를 공유하게 된다면 뷰와 관련된 작업의 책임을 어디서 가져가야 할지 불분명해지고 상태 관리가 복잡해질 수 있습니다.
또 뷰 컨트롤러가 해제되었으나 공유된 뷰가 남아있으면 의도치 않은 동작이 발생하거나 메모리 누수가 발생할 확률도 높아지게 됩니다.


Life Cycle

뷰 컨트롤러에는 앱과 같이 생명주기가 존재합니다.
그리고 각 생명주기에 맞게 호출되는 메서드들이 존재합니다.

순서를 다시 정리해보자면 다음과 같습니다.

  • init
  • load view
  • view did load
  • view will appear
  • view is appearing
  • view did appear
  • view will disappear
  • view did disappear
  • deinit

처음 초기화 후 메모리에 로드됩니다.
이후 사용자에게 나타나는 과정이 3단계로 나누어지고 다른 뷰 컨트롤러로 이동하는 등의 이유로 사용자가 볼 수 없게 될 때 사라지는 과정이 2단계로 이루어져있습니다.
이후 완전히 필요없어진다면 객체는 메모리에서 내려가게 됩니다.

다음 이미지는 사용자가 뷰컨트롤러를 볼 수 있는 경우와 상태 전환을 나타내고 있습니다.

여기서 will 메서드는 주로 did 메서드와 쌍을 이루게 됩니다.
그렇다고 반드시 저 둘만이 짝을 이루는 것은 아니고 반대편의 will 메서드와도 쌍을 이루기도 합니다.

did와 정확히 짝지어지지 않는 경우는 화면 전환 중 인터럽트가 발생하거나 생명주기 단계를 건너뛰는 경우 did 메서드가 호출되지 않을 수 있습니다.
또는 애니메이션의 경우 뷰가 완전히 나타나기 전까지 진행되다가 나타난 후 종료하는 것이 자연스러우나 네트워크 처리같은 경우엔 뷰 컨트롤러가 보여지는 동안 사용하다가 다른 화면으로 넘어가기 시작할 때 즉, 반대편 will 메서드가 실행될 때 종료해야 자연스럽습니다.

중요한 건 will 메서드에서 시작한 메서드는 반드시 쌍을 이루는 did 메서드에서든 반대편 will 메서드에서든 종료되어야 한다는 것입니다. 그리고 작업의 특성에 따라 적절한 종료 시점은 다른 생명 주기에 위치할 수 있다는 점입니다.


Is Appearing?

Appear의 단계는 Disappear와 달리 중간에 한 단계가 더 존재합니다.
왜 그럴까요?? 왜 Disappear는 차별받은 걸까요?

먼저 appear과 관련하여 기존의 willdid만으로 이루어진 상태에서는 정밀한 애니메이션이나 UI처리가 어려웠습니다.
will이 호출되는 시점에선 뷰의 위치, 크기, 트레이트 등이 지정되지 않은 경우가 존재하고,
did가 호출되는 시점은 이미 사용자에게 모든 화면이 표시되었으므로 UI 처리가 늦을 수 있습니다.

In contrast to viewWillAppear(_:), the system calls this method after it adds the view controller’s view to the view hierarchy, and the superview lays out the view controller’s view. By the time the system calls this method, both the view controller and its view have received updated trait collections and the view has accurate geometry.

이러한 문제를 해결하기 위한 is appearing 라이프 구간은 생각보다 최근인 WWDC2023에서 추가되었습니다.
공식문서에 따르면 viewWillAppear와 달리 viewIsAppearing은 뷰 컨트롤러의 뷰가 뷰 계층에 추가되고 상위뷰가 뷰 컨트롤러의 뷰를 모두 레이아웃 한 이후 호출됩니다.

즉 보다 적절한 타이밍에 UI 업데이트를 제공할 수 있도록 돕기 위해 추가된 것으로 뷰가 사라지는 과정에는 이러한 세부적인 조정이 필요 없기에 isDisappearing 메서드가 없는 듯 합니다.

사진에서 보듯 willAppearisAppearing은 콜백되는 순서의 차이가 존재하나 모두 동일한 CATransaction 내에서 발생합니다.
따라서 사용자는 동시에 두 메서드의 처리 결과를 보게 됩니다.
대신 앞서 말했듯 isAppearing은 모든 UI의 트레이트나 지오메트리가 최신 상태로 업데이트 된 상태에서 호출되므로 애플은 뷰를 업데이트 할 때 willAppear 대신 isAppearing을 사용할 것을 권장하고 있습니다.


그리고 다음과 같은 경우에만 willAppear를 사용하여 처리할 것을 권합니다.

  • 뷰 전환이 시작되기 전에 콜백이 필요한 경우
    • transitionCoordinator에 접근하여 함께 실행 될 alongside 애니메이션을 추가해야 하는 경우.
      (여기서 alongside animation 이란 뷰 컨트롤러 전환 애니메이션과 동시에 프레임워크에서 실행하도록 지시하는 애니메이션을 의미)
  • 뷰 컨트롤러 또는 뷰의 트레이트, 계층 구조나 지오메트리에 의존하지 않는 작업을 수행해야 하는 경우
    • willAppear에서 데이터베이스 알림을 등록하고, didDisappear에서 이를 등록 해제하는 경우와 같이 균형 잡힌 콜백이 필요한 작업.


추가로 위 표를 참고하면 좀 더 메서드를 호출할 시점을 정하는 데 도움이 될 것입니다.


Layout Method


마지막으로 살펴볼 것은 앞서 봤던 view로 시작되는 메서드 목록 중 라이프 사이클에 포함되지 않는 메서드 2개입니다.

먼저 알아볼 것은 layoutSubviews로 뷰의 하위뷰(subview)를 재배치하거나 조정할 때 사용되는 메서드입니다.
이 메서드는 하위 뷰가 추가, 삭제 되거나 위치가 바뀌는 등의 상황에서 자동으로 호출됩니다.

애플은 서브뷰의 레이아웃과 관련하여 원하는 동작이 자동으로 지원되지 않을 때만 재정의할 것을 권장합니다.
추가로 이 메서드를 직접 호출하는 대신 다음 UI 업데이트 이전에 setNeedsLayout를 호출 할 것을 권장하고 있습니다.
만약 즉시 레이아웃을 업데이트 하려면 layoutIfNeeded를 호출하라고 합니다.

이렇게 보통은 자동으로 처리되는 layoutSubviews 전후로 호출되는 viewWillLayoutSubviewsviewDidLayoutSubviews가 마지막 목차의 주인공입니다.

이 두 메서드는 layoutSubviews가 실행될 때마다.
즉 전환이 일어나는 상황이라면 뷰가 표시되는 상황동안 몇 번이든 호출될 수 있습니다.
이 부분이 단 한 번만 실행되는 viewIsAppearing과 가장 큰 차이점입니다.

다른 차이로는 layoutSubviews과 관련 메서드들은 레이아웃이 조정될 때 호출된다면 viewIsAppearing은 레이아웃이 조정되지 않을 때도 호출됩니다.

따라서 반복적인 호출이 필요한 UI업데이트 메서드는 layoutSubviews 관련 메서드에, 단 한 번만 필요한 초기화나 뷰 업데이트 등은 viewIsAppearing에 알맞게 넣어야 합니다.

호출 조건과 목적이 다르다는 점을 염두에 두고 상황에 잘 맞게 선택해야 합니다.


참고 문서

Apple 공식 문서: viewIsAppearing
Apple 공식 문서: Displaying and Managing Views
Apple 공식 문서: UIViewController 전체

2개의 댓글

comment-user-thumbnail
2024년 12월 4일

우주최초 계엄령 중에 TIL 쓴 사람

1개의 답글