UIViewController의 생명주기는 다음과 같은 주요 메서드로 구성됩니다:
init(nibName:bundle:) / init(coder:): 초기화loadView: view 계층 생성viewDidLoad: view가 로드됨 (초기 설정을 위한 이상적인 장소)viewWillAppear / viewDidAppear: view가 나타나기 전/후viewWillDisappear / viewDidDisappear: view가 사라지기 전/후deinit: 컨트롤러 삭제메서드 호출 순서:
loadView, 그 후 viewDidLoad)viewWillAppear/viewWillDisappear, 그 다음 viewDidAppear/viewDidDisappear가 호출됨deinit세부 사항:
viewDidLoad에서 view의 크기에 접근하지 않는 것이 좋음 — 그것들이 유효하지 않을 수 있음deinit 또는 viewWillDisappear에서 해제하는 것이 중요함viewDidLoad에서, viewWillAppear에서는 하지 말아야 함 — 그렇지 않으면 매번 나타날 때마다 중복이 발생할 수 있음예시:
class MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() setupViews() setupBindings() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // 알림 구독 } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // 알림 구독 해제 } deinit { // 정리 작업 } }
질문:
view controller가 생명주기 밖에서 view 속성에 접근하는 것이 허용됩니까? (예: 초기화 자에서)
답변:
아니요, loadView가 호출되기 전까지는 view와 관련된 모든 속성이 초기화되지 않을 수 있습니다. loadView/viewDidLoad 밖에서 이들에 접근하면 충돌이 발생합니다.
예시:
// 오류: self.view가 아직 초기화되지 않음! init() { super.init(nibName: nil, bundle: nil) self.view.backgroundColor = .red //충돌 }
이야기
프로젝트가 초기화 중 self.view에 미리 접근하여 충돌이 발생했음 — view가 생성되지 않았습니다.
이야기
대규모 프로젝트에서 viewWillDisappear 및/또는 deinit에서 NotificationCenter 또는 delegate에서 구독 해제를 잊어서 메모리 누수가 발생했습니다 (NotificationCenter가 view controller를 참조하고 있어 해제되지 않고 이벤트를 계속 수신함).
이야기
viewWillAppear에서 매번 새로운 서브뷰가 view에 추가되었음 (예: 로딩 인디케이터 표시), 존재 여부를 확인하지 않았습니다. 결과적으로 화면에 복제된 인디케이터가 점점 늘어나면서 UI가 고장났습니다.