viewWillDisappear는 UIKit이 사용자의 디스플레에서 화면이 사라지기 직전에 호출하는 UIViewController 메소드입니다. Apple Developer Documentation에 따르면, 이 메소드는 animated 매개변수를 받으며 push, pop, present, dismiss 및 탭 전환 시 작동합니다. viewWillDisappear는 상태를 저장하고 리소스를 올바르게 정리하는 기본 장소입니다.
주요 포인트
viewWillDisappear는 UIKit이 컨트롤러의 뷰가 화면에서 사라지기 직전에 호출하는 UIViewController 메소드입니다. 이 순간에는 화면이 사용자에게 아직 보이지만, 전환이 이미 시작되었습니다: NavigationController가 push/pop 애니메이션을 시작했고, 모달 뷰가 닫히기 시작했거나, TabBar가 다른 탭으로 전환하기 시작했습니다. 개발자는 화면이 아직 접근 가능해야 하지만 숨기기 준비를 하는 작업을 수행하기 위해 이 메소드를 오버라이드합니다.
화면이 숨은 후에 작동하는 viewDidDisappear와 달리, viewWillDisappear는 사용자가 아직 인터페이스를 볼 수 있는 동안 데이터를 저장하고 리소스를 해제할 마지막 기회를 제공합니다. 이것은 UX에 극힐 중요합니다 — 초안 저장이나 타이머 정지는 사용자가 다른 화면으로 전환하기 전에 일어나야 합니다.
메소드는 animated 매개변수를 받습니다. 이는 사라짐이 애니메이션되는지 여부를 나타냅니다. true는 UIKit이 애니메이션된 전환을 수행한다는 것이고, false는 화면이 즐각 사라진다는 것입니다. 예를 들어 애니메이션 없이 dismiss하거나 프로그램적으로 계층에서 제거할 때같습니다.
viewWillDisappear는 현재 화면이 더 이상 활성이 아니게 되는 모든 시나리오에서 호출됩니다. iOS 개발에 특정적인 주요 사례를 살펴보겠습니다.
UINavigationController가 새 컨트롤러를 push하면, 전환 애니메이션이 시작될 때 현재 컨트롤러에서 viewWillDisappear가 호출됩니다. 이 순간에 현재 화면은 그 위로 슬라드 되는 새 컨트롤러 아래에서 아직 보입니다. 이것이 viewWillDisappear가 animated = true로 작동하는 표준 시나리오입니다.
사용자가 뒤로 가기 버튼을 누르거나 인터랙티브 스와이프 백을 수행하면, 현재 컨트롤러에서 viewWillDisappear가 호출됩니다. 인터랙티브 제스처의 경우 사용자가 마음을 바꾸어 화면을 원래 위치로 돌리면 이 호출이 취소될 수 있습니다. 상태 저장을 설계할 때 고려해야 할 중요한 특징입니다.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
saveDraftData()
NotificationCenter.default.removeObserver(self)
}
모달 뷰가 닫히면, dismiss 애니메이션이 시작될 때 닫히는 컨트롤러에서 viewWillDisappear가 호출됩니다. 이 시점에서 데리게이트나 클로저를 통해 결과를 되돌릴 수 있습니다. 왜냐하면 모달을 표시한 컨트롤러가 아직 제어를 다시 찾지 못했기 때문입니다.
UITabBarController는 사용자가 다른 탭을 터치한 직후에 떠나는 탭의 컨트롤러에서 viewWillDisappear를 호출합니다. 현재 탭에 활성 프로세스가 있는 경우 — 미디어 재생, 파일 다운로드, 타이머 — 이 곳에서 일시 중단하거나 멈추어야 합니다.
viewWillDisappear는 리소스 및 상태 관리와 관련된 특정 작업을 해결합니다. 코드 예시를 통해 주요 시나리오를 살펴보겠습니다.
viewWillDisappear의 가장 중요한 작업은 현재 화면에서 사용자가 입력하거나 수정한 데이터를 저장하는 것입니다. 메시지 초안, 편집된 폼 필드, 선택된 설정 — 이 모든 것은 화면이 사라지기 전에 저장되어야 합니다. 지속성을 위해 Core Data, UserDefaults 또는 파일 저장소를 사용하세요.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
guard hasUnsavedChanges else { return }
draftStorage.save(currentDraft)
}
viewWillAppear 또는 viewDidLoad에서 구독한 NotificationCenter, KVO 및 Combine 게재들은 viewWillDisappear에서 취소해야 합니다. 그렇지 않으면 알림이 숨겨진 화면에 도착하여 사용자가 보지 못하는 UI 업데이트가 발생하거나, 더 심각하게는 이미 해제된 객체에 접근하여 충돌이 발생할 수 있습니다.
viewDidAppear에서 시작된 UIView 애니메이션과 Timer 또는 DispatchSource를 통해 실행되는 타이머는 viewWillDisappear에서 정지해야 합니다. 숨겨진 화면에서 계속되는 애니메이션은 사용자에게 이득이 없이 GPU와 배터리를 낭비합니다. 타이머에서 invalidate를, 레이어에서 removeAllAnimations을 호출하여 명시적으로 정지하세요.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
countdownTimer?.invalidate()
countdownTimer = nil
loadingIndicator.layer.removeAllAnimations()
}
컨트롤러가 결과를 얻기 위해 열린 경우 — 항목 선택, 텍스트 입력, 작업 확인 — viewWillDisappear는 원래 컨트롤러가 아직 스택에 있고 데이터를 받을 수 있는 마지막 순간입니다. deinit이 호출되기 전에 데리게이트나 클로저를 호출하세요.
신뢰할 수 있는 상태 저장은 iOS 개발에서 가장 어려운 작업 중 하나입니다. viewWillDisappear는 중요하지만 전략의 유일한 요소는 아닙니다. 포괄적인 접근 방식을 살펴보겠습니다.
레벨 1 — viewWillDisappear에서 저장. 되돌아왔을 때 그대로 사용할 수 있는 가벼운 데이터의 빠른 저장. UI 상태에 적합: 스크롤 위치, 선택된 세그먼트, 입력 필드의 텍스트. 문제: 취소된 인터랙티브 pop 제스처에서는 사용자가 화면에 그대로 있던 것과 관계없이 저장이 일어나며 데이터가 필요 없이 겹쳐쓰입니다.
레벨 2 — viewDidDisappear에서 저장. 처음 레벨의 저장을 복제하지만 화면이 확실히 숨은 후에만 작동합니다. 이것은 취소된 제스처에 대한 보호 장치입니다. 그러나 이미 viewWillDisappear에서 알림 구독을 해지했다면 viewDidDisappear는 일부 데이터에 접근하지 못할 수 있습니다.
레벨 3 — 애플리케이션 알림을 통한 저장. UIApplication.willResignActiveNotification과 UIApplication.didEnterBackgroundNotification은 앱이 백그라운드되는 것을 캘처합니다. 사용자가 앱을 최소화한 경우 viewWillDisappear가 호출되지 않았을 수 있지만 이 알림을 통한 저장은 세션 종료 시 데이터 무결성을 보장합니다.
| 레벨 | 메소드/알림 | 신뢰성 | 사용 |
|---|---|---|---|
| 1 | viewWillDisappear | 높음 | UI 상태, 초안 |
| 2 | viewDidDisappear | 매우 높음 | 중요 데이터 |
| 3 | willResignActive | 최고 | 앱 백그라운드 시 |
권장: 중요한 사용자 데이터에는 세 레벨 모두를 조합하여 사용하세요. 비중요 상태에는 처음 레벨만으도 충분합니다. 동일한 데이터를 여러 번 저장하지 않는 것이 중요합니다 — 마지막 저장 이후에 데이터가 변경되었음을 나타내는 dirty 플래그를 사용하세요.
사용자가 데이터를 입력하는 CRUD 화면의 전략에 특별한 주의를 기울여야 합니다. 이러한 화면에서는 viewWillDisappear에서 모든 키 스트로크를 저장하는 것이 권장되지 않습니다 — 그것은 과잉입니다. Timer 를 통한 지연 (debounce) 이 있는 자동 저장을 사용하고, viewWillDisappear는 저장되지 않은 변경 사항이 있는 경우에만 최종 강제 저장을 위해 사용하세요. 이 접근 방식은 성능과 데이터 무결성을 균형있게 유지합니다.
Core Data를 사용하는 앱의 경우, managed object context에 실제 변경이 있을 때만 viewWillDisappear에서 saveContext를 호출하는 것이 추가 조치입니다. 저장 전에 context.hasChanges를 확인하면 persistent store에 대한 필요 없는 쓰기 작업을 맡고 디바이스의 배터리 수명을 연장합니다. 이 확인을 applicationDidEnterBackground에서의 전역 저장과 결합하세요.
잘못된 사용 viewWillDisappear은 데이터 손실, 메모리 눌수 및 불안정한 앱 동작을 초래할 수 있습니다. 많은 iOS 개발자들이 저지르는 에를 살펴보겠습니다.
처음 실수 — viewWillDisappear에서만 데이터 저장. 위에서 년른 바와 같이, 인터랙티브 pop 제스처에서는 화면이 사라지지 않았다도 메소드가 호출됩니다. 저장에 부작용이 있는 경우 — 서버로 데이터 전송, 상태 변경 — 이것이 잘못된 작동을 볼러야 할 수 있습니다. isBeingDismissed 또는 isMovingFromParent 확인을 추가하세요.
둘째 실수 — NotificationCenter 구독을 해지하지 않는 것. iOS에서 가장 흘한 메모리 눌수 중 하나입니다. viewWillAppear에서 UIResponder.keyboardWillShowNotification에 구독했지만 viewWillDisappear에서 구독을 해지하지 않으면 클로저가 계속 호출됩니다. 컨트롤러가 deinit될 때 클로저가 해제된 객체를 참조하여 액 충돌이 확실히 발생합니다.
셋째 실수 — 무거운 동기 작업 수행. viewWillDisappear에서 대량의 데이터를 저장하거나 Core Data 또는 파일 시스템에 쓰는 것은 메인 스레드를 차단합니다. 작업이 전환 애니메이션보다 길게 걸리면 UIKit이 스레드를 일시 중단하고 인터페이스가 멈춰 버립니다. 무거운 저장은 백그라운드 큐로 옮겨주세요.
넣째 실수 — super 호출을 잊는 것. super.viewWillDisappear를 호출하지 않으면 이 메소드를 내부 상태에 사용하는 UINavigationController와 UITabBarController가 작동하지 않을 수 있습니다. Apple 문서에 따라 항상 super를 먼저 또는 마지막에 호출하세요.
이 문제는 활성적인 멀티태스킹과 앱 전환이 있는 iOS에서 더 심각합니다. 다섯번째 실수 — viewWillDisappear에서 저장 후 DispatchQueue.main.async 사용. super.viewWillDisappear를 호출한 후 메인 큐에 블록을 비동기적으로 보내면, 블록 실행 시점에 컨트롤러가 아직 존재한다는 보장이 없습니다. 해제된 메모리에 접근하거나 액 충돌을 맡을 때는 클로저 내에서 항상 약한 참조 [weak self]를 사용하세요.
자주 묻는 질문
viewWillDisappear는 사라짐이 시작될 때 호출되며 화면이 아직 보입니다. viewDidDisappear는 화면이 완전히 숨고 애니메이션이 완료된 후에 호출됩니다.
저장을 확인하려면 viewDidDisappear를 사용하거나 viewWillDisappear 내에서 isMovingFromParent와 isBeingDismissed 프로퍼티를 확인하여 화면이 실제로 사라질 것인지 확인하세요.
네, 반드시 self와 함께 블록 또는 셀렉터를 사용하는 경우입니다. ARC는 NotificationCenter 구독을 관리하지 않습니다. iOS 9+에서 블록을 사용하는 경우 약한 참조를 사용하고 viewWillDisappear에서 구독을 해지하세요.
방법이 없습니다 — force quit은 생명 주기 메소드를 호출하지 않습니다. 앱 종료 시 확실한 저장을 위해서는 UIApplication.willTerminateNotification을 사용하거나 데이터가 변경됨에 따라 실시간으로 저장하세요.
네, 인터랙티브 pop 제스처에서 UIKit이 제스처가 시작된 직후에 viewWillDisappear를 호출합니다. 사용자가 제스처를 취소하면 화면이 그대로 보이지만 메소드는 이미 실행되었습니다. 항상 isMovingFromParent를 확인하세요.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.