안녕하세요 제이븐입니다 😁
이번에 포스팅할 주제는 UIViewController의 생명주기입니다.
아래 순서대로 하나씩 알아보겠습니다.
iOS에서는 스토리보드, Xib, CodeBase 세 가지 방식으로 ViewController를 생성할 수 있습니다.
위에 방법 중 어떤 방법으로 진행하던 ViewController가 생성되고 표시되고 소멸되는 Life Cycle을 제대로 이해야야지
사용자 인터페이스를 개선하고 제대로된 코드를 작성할 수 있습니다.
UIViewController의 생명주기 메서드와 그림
ViewController의 View가 처음으로 로드될 때 호출되며, ViewController의 Main View 프로퍼티를 생성하고 초기화하는 책임을 집니다.
기본적으로 loadView()
는 StoryBoard나 nib 파일에서 뷰를 로드합니다. 그래서 StoryBoard, Xib를 사용하는 프로젝트에서는 직접 loadView 호출하는 것을 지양합니다.
하지만 CodeBase로 작업하는 경우에는 이 메서드를 오버라이드하여 직접 뷰를 생성하고 설정해야 됩니다.
사용시 주의해야될 점
ViewController의 View가 아직 메모리에 로드되지 않았을 때 이를 강제로 로드하는 역할을 합니다. CodeBase에서 View를 즉시 로드할 필요가 있을 때 사용됩니다.
loadViewIfNeeded()
메서드는 별다른 파라미터 없이 호출됩니다. ViewController 내부에서 뷰의 구성 요소를 설정하기 전에 뷰가 로드되었는지 확실하게 하고 싶을 때 사용할 수 있습니다.
func configure() {
loadViewIfNeeded()
}
사용시 주의할 점
불필요한 로드 방지
라이프사이클 메서드 중복 호출
loadViewIfNeeded()
를 사용하면 loadView와 viewDidLoad가 호출됩니다. 따라서 이 메서드를 호출하기 전에 이미 viewDidLoad에서 수행한 설정이 중복 실행되지 않도록 주의해야 합니다.성능 고려
ViewController가 뷰 계층 구조를 메모리에 로드한 후에 한 번만 호출되는 메서드입니다. 이 메서드는 뷰 계층 구조가 nib 파일에서 로드되었는지 또는 loadView() 메서드에서 프로그래밍 방식으로 생성되었는지에 관계없이 호출됩니다. 일반적으로 이 메서드를 재정의하여 nib 파일에서 로드된 뷰에 대한 추가 초기화를 수행합니다.
viewDidLoad가 호출되는 시점에서 뷰는 아직 화면에 표시되지는 않았지만, 모든 뷰 객체는 초기화되고 준비되어 있습니다.
viewDidLoad의 주요 역할
ViewController의 뷰가 뷰 계층 구조에 추가되기 전과 뷰를 표시하기 위한 애니메이션이 구성되기 전에 호출됩니다. 이 메서드는 뷰가 화면에 나타날 때 마다 호출됩니다.
viewWillAppear의 주요 역할
사용 시 주의할 점
뷰가 서브뷰의 레이아웃을 조정하기 직전에 호출되는 메서드입니다.
이 메서드는 뷰의 bounds가 변경될 때마다 호출됩니다. 일반적으로 뷰의 배치나 레이아웃을 조정해야 할 때 사용됩니다.
viewWillLayoutSubviews 주요 역할
호출 시점
호출 순서
뷰가 서브뷰의 레이아웃을 조정한 후에 호출되는 메서드입니다.
메서드는 뷰의 bounds가 변경될 때마다 호출되며, 레이아웃 작업이 완료된 후 후속 작업을 수행하는 데 사용됩니다.
viewDidLayoutSubviews 주요 역할
ViewController의 뷰가 화면에 완전히 표시된 후에 호출되는 메서드입니다.
viewDidAppear 주요 역할
ViewController의 뷰가 뷰 계층에서 제거되기 직전에 호출되는 메서드입니다.
viewWillDisappear 주요 역할
ViewController의 뷰가 뷰 계층에서 제거된 후에 호출되는 메서드입니다.
viewDidDisappear 주요 역할
ViewController에서 Present, Push 등으로 새로운 화면이 나타나고 없어질 때 LifeCycle의 어떤 메서드가 호출되는지 알아보겠습니다.
메인 화면이 나타나면 아래 처럼 loadView -> viewDidLoad -> viewWillAppear -> viewDidAppear 이 불리는 것을 볼 수 있습니다.
A: loadView
A: viewDidLoad
A: viewWillAppear
A: viewDidAppear
Present에도 pageSheet
, fullScreen
등 화면을 전체로 덮으면서 올라오는 동작과 Main을 다 덮지 않고 올라오는 동작이 있고 이 두 동작이 A(Main)에 LifeCycle에 어떠한 영향을 끼치는지 하나 하나 보겠습니다
이 방식으로 새로운 B라는 ViewController가 올라가게 된다면 A(Main)은 DisAppear가 호출될까요?
답은 아닙니다 A(Main)에 영향을 주지않습니다 정확하게는 A(Main)의 DisAppear가 호출되지 않습니다.
A: loadView
A: viewDidLoad
A: viewWillAppear
A: viewDidAppear
B: loadView
B: viewDidLoad
B: viewWillAppear
B: viewDidAppear
그렇다면 이어서 아래처럼 B를 아래로 땡겼다가 다시 원래 위치로 돌리게 된다면 어떻게 될까요??
B를 아래로 당겨서 없애려는 순간 viewWillDisappear()
가 호출되고 다시 되돌리면 viewWillAppear()
-> viewDididAppear()
가 호출됩니다.
당연히 뷰를 아예 제거한다면 viewDidDisAppear()이 호출될 것이고 A(Main)뷰는 DisAppear 된 적이 없기 때문에 LifeCycle 메서드를 호출하지 않을 것 입니다.
B: viewWillDisappear
B: viewWillAppear
B: viewDidAppear
그렇다면 위에와 다르게 fullScreen으로 A(Main)뷰를 덮는 화면을 띄우면 어떻게 될까요??
위에 동작과 다르게 B뷰가 로드되면 A(Main)은 WillDisAppear를 호출하고 B뷰가 DidAppear되는 순간 A(Main)뷰는 DidAppear를 호출합니다
B: loadView
B: viewDidLoad
A: viewWillDisappear
B: viewWillAppear
B: viewDidAppear
A: viewDidDisappear
BView를 종료하고 -> A(Main)으로 돌아가게 된다면
아래와 같이
viewWillDisappear()
를 호출합니다.viewDidLoad()
이후의 viewWillAppear()
, viewDididAppear()
를 호출viewDididAppear()
화면에 나타나면 뒤에 BView는 완전히 종료되면서 viewDidDisappear()
를 호출합니다.B: viewWillDisappear
A: viewWillAppear
A: viewDidAppear
B: viewDidDisappear
마지막으로 네비게이션의 push로 C뷰로 이동 했을 경우입니다
CView가 push되면서 나타낼때는 B뷰가 fullScreen으로 나타날때와 같습니다.
하지만 Back 버튼을 눌러서 pop하는 경우는 뭐가 다를까요??
코드를 보면 알다시피
1. viewWillDisappear가 호출됩니다.
2. A(Main)이 viewWillAppear()가 호출된 뒤
3. C에서 viewDidDisAppar()이 호출된 후에 A(Main)뷰가 DidAppear이 됩니다.
present와 다른 점은 A(Main)이 DidAppear된 후에 present된 뷰가 DisAppear이 되고
navigation은 C뷰가 DisAppear 이후에 A가 DidAppear된다는 점 입니다.
C: viewWillDisappear
A: viewWillAppear
C: viewDidDisappear
A: viewDidAppear
ViewController Life Cycle 그리고 호출되는 메서드에 대해서 포스팅 했습니다.
해당 라이프 사이클에 관련된 메서드들이 어떤 상황에서 호출되는지, 각 메서드에 어떤걸 넣어야되는지 다시 한 번 공부하는 시간이 였습니다
질문과 피드백은 언제나 환영입니다 🙇🙇