viewWillDisappear is a UIViewController method that UIKit calls just before the screen starts disappearing from the user’s display. According to Apple Developer Documentation, this method receives an animated parameter and fires on push, pop, present, dismiss and tab switching. viewWillDisappear is the primary place for saving state and properly cleaning up resources.
Key Takeaways
viewWillDisappear is a UIViewController method that UIKit calls just before the View of the controller starts disappearing from the screen. At this moment the screen is still visible to the user, but the transition has already been initiated: NavigationController started the push/pop animation, the modal view started closing, or TabBar started switching to another tab. The developer overrides this method to perform operations that require the screen to still be accessible but is preparing to hide.
Unlike viewDidDisappear, which fires after the screen is hidden, viewWillDisappear provides the last opportunity to save data and release resources while the user can still see the interface. This is critically important for UX — saving a draft or stopping a timer must happen before the user switches to another screen.
The method accepts an animated parameter, which indicates whether the disappearance is animated. A value of true means UIKit is performing an animated transition, false means the screen disappears instantly, for example during a non-animated dismiss or programmatic removal from the hierarchy.
viewWillDisappear is called in all scenarios where the current screen ceases to be active. Let’s review the main cases specific to iOS development.
When UINavigationController performs a push of a new controller, viewWillDisappear is called on the current one at the start of the transition animation. At this moment the current screen is still visible beneath the new controller sliding over it. This is the standard scenario where viewWillDisappear fires with animated = true.
When the user taps the back button or performs an interactive swipe back, viewWillDisappear is called on the current controller. With an interactive gesture this call can be cancelled if the user changes their mind and returns the screen to its place. This is an important feature to consider when designing state saving.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
saveDraftData()
NotificationCenter.default.removeObserver(self)
}
When closing a modal view, viewWillDisappear is called on the closing controller at the beginning of the dismiss animation. At this point you can pass results back via a delegate or closure, since the controller that presented the modal has not yet regained control.
UITabBarController calls viewWillDisappear on the controller of the departing tab right after the user touches another tab. If the current tab has active processes — media playback, file download, timer — they should be paused or stopped here.
viewWillDisappear solves specific tasks related to resource and state management. Let’s review the key scenarios with code examples.
The most important task of viewWillDisappear is saving data that the user entered or modified on the current screen. Message drafts, edited form fields, selected settings — all of this should be saved before the screen disappears. Use Core Data, UserDefaults or file storage for persistence.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
guard hasUnsavedChanges else { return }
draftStorage.save(currentDraft)
}
NotificationCenter, KVO and Combine publishers that you subscribed to in viewWillAppear or viewDidLoad must be cancelled in viewWillDisappear. If not, notifications will arrive on the hidden screen, causing UI updates that the user does not see, or — worse — crashes due to accessing already deallocated objects.
UIView animations started in viewDidAppear and timers running via Timer or DispatchSource must be stopped in viewWillDisappear. Continuing animations on a hidden screen waste GPU and battery with no benefit to the user. Stop them explicitly by calling invalidate on timers and removeAllAnimations on layers.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
countdownTimer?.invalidate()
countdownTimer = nil
loadingIndicator.layer.removeAllAnimations()
}
If a controller was opened to get a result — selecting an item, entering text, confirming an action — viewWillDisappear is the last moment when the original controller still exists in the stack and can receive data. Call the delegate or closure before deinit is invoked.
Reliable state saving is one of the most challenging tasks in iOS development. viewWillDisappear is an important but not the only element of the strategy. Let’s look at a comprehensive approach.
Level 1 — saving in viewWillDisappear. Quick saving of lightweight data that should be available immediately upon return. Suitable for UI state: scroll position, selected segment, text in input fields. Problem: on a cancelled interactive pop gesture, saving occurs even though the user stayed on the screen — data gets overwritten unnecessarily.
Level 2 — saving in viewDidDisappear. Duplicates the save from the first level but fires only after the screen is guaranteed to be hidden. This is a safeguard against cancelled gestures. However, if you already unsubscribed from notifications in viewWillDisappear, viewDidDisappear may not have access to some data.
Level 3 — saving via application notifications. UIApplication.willResignActiveNotification and UIApplication.didEnterBackgroundNotification catch app backgrounding. If the user minimized the app, viewWillDisappear may not have been called — but saving through these notifications guarantees data integrity when the session ends.
| Level | Method/Notification | Reliability | Usage |
|---|---|---|---|
| 1 | viewWillDisappear | High | UI state, drafts |
| 2 | viewDidDisappear | Very High | Critical data |
| 3 | willResignActive | Maximum | On app backgrounding |
Recommendation: use a combination of all three levels for critical user data. For non-critical state, the first level is sufficient. It is important not to re-save the same data multiple times — use a dirty flag indicating that data has changed since the last save.
Special attention should be paid to the strategy for CRUD screens where the user enters data. On such screens it is not recommended to save every keystroke in viewWillDisappear — that is excessive. Use auto-save with delay (debounce) via Timer, and use viewWillDisappear only for final forced saving if there are unsaved changes. This approach balances performance and data integrity.
For apps using Core Data, an additional measure is to call saveContext in viewWillDisappear only when there are actual changes in the managed object context. Checking context.hasChanges before saving prevents unnecessary writes to the persistent store and extends device battery life. Combine this check with global saving in applicationDidEnterBackground.
Incorrect usage of viewWillDisappear can lead to data loss, memory leaks and unstable app behavior. Let’s review frequent iOS developer mistakes.
First mistake — saving data only in viewWillDisappear. As discussed above, with an interactive pop gesture the method is called even if the screen did not disappear. If saving has side effects — sending data to the server, changing state — this can lead to false triggers. Add a check for isBeingDismissed or isMovingFromParent.
Second mistake — failing to unsubscribe from NotificationCenter. This is one of the most common memory leaks in iOS. If you subscribed in viewWillAppear to UIResponder.keyboardWillShowNotification but did not unsubscribe in viewWillDisappear, the closure continues to be called. Upon controller deinit, the closure will reference a deallocated object — app crash guaranteed.
Third mistake — performing heavy synchronous operations. Saving large amounts of data, writing to Core Data or the file system in viewWillDisappear blocks the main thread. If the operation takes longer than the transition animation, UIKit pauses the thread and the interface freezes. Offload heavy saving to background queues.
Fourth mistake — forgetting to call super. Not calling super.viewWillDisappear can break UINavigationController and UITabBarController, which use this method for their internal state management. Always call super first or last, following Apple’s documentation.
This problem is compounded on iOS with active multitasking and app switching. Fifth mistake — using DispatchQueue.main.async after saving in viewWillDisappear. If you asynchronously dispatch a block to the main queue after calling super.viewWillDisappear, there is no guarantee the controller still exists by the time the block executes. Always use weak references [weak self] inside closures to prevent accessing deallocated memory and prevent app crashes.
Frequently Asked Questions
viewWillDisappear is called at the beginning of the disappearance when the screen is still visible. viewDidDisappear is called after the screen is completely hidden and the animation has finished.
Use viewDidDisappear to confirm saving or check the isMovingFromParent and isBeingDismissed properties inside viewWillDisappear to determine whether the screen will actually disappear.
Yes, absolutely if you use blocks or selectors with self. ARC does not manage NotificationCenter subscriptions. In iOS 9+ for blocks use a weak reference and unsubscribe in viewWillDisappear.
No way — force quit does not call Lifecycle methods. For guaranteed saving on app termination use UIApplication.willTerminateNotification or save data in real time as it changes.
Yes, on an interactive pop gesture UIKit calls viewWillDisappear right after the gesture starts. If the user cancels the gesture, the screen remains visible but the method has already fired. Always check isMovingFromParent.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also