Detect when a presented view controller is dismissed
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
When one view controller presents another, the presenting screen often needs to know when the modal goes away so it can refresh data, resume work, or update its UI. In UIKit, the correct detection strategy depends on how the dismissal happens: by button tap, by interactive swipe, or by code.
Notifying the Presenter Explicitly
If the presented controller decides when it is done, the cleanest option is to notify the presenter before dismissal. A delegate works well because it makes the data flow explicit and avoids hidden behavior.
This pattern is easy to review and test. The presented controller says it finished, and the presenting controller updates itself in one place.
Handling Swipe-to-Dismiss on Modern Sheets
On current iOS versions, a sheet can disappear without the user tapping your own Done button. If the modal uses swipe-to-dismiss, you should also listen to UIPresentationController callbacks. The key method is presentationControllerDidDismiss(_:).
This delegate fires after the interactive dismissal finishes. It is the right hook when you care about the modal disappearing regardless of whether the user tapped a button or swiped the sheet away.
Detecting Dismissal Inside the Presented Controller
Sometimes the presented controller itself needs to know that it is being removed, perhaps to stop a task or write a temporary draft. In that case, override viewDidDisappear(_:) and check isBeingDismissed.
That check matters because viewDidDisappear(_:) also runs when another controller covers the screen. Without the extra guard, you may run cleanup at the wrong time.
Using a Dismiss Completion Block
If the presenting controller is the one calling dismiss(animated:completion:), the completion block can also be useful. That is a good place for small follow-up work that should run only after the animation has finished, such as reloading a table or starting a new presentation flow.
Common Pitfalls
A common mistake is relying only on the Done button path. With sheet presentations, users can often dismiss interactively, which bypasses your button handler. If you need guaranteed notification, add the presentation controller delegate as well.
Another problem is setting presentationController?.delegate too late. Configure it before presenting the controller so UIKit knows where to send dismissal events.
Be careful with memory management. Delegates should normally be weak, and closure callbacks should avoid strong reference cycles when they capture a presenting controller.
Finally, do not confuse dismissal with navigation popping. If the controller lives inside a navigation stack, isMovingFromParent is the property that tells you it was popped. isBeingDismissed is for modal dismissal.
Summary
- Use a delegate or callback when the presented controller finishes through its own UI.
- Add
presentationControllerDidDismiss(_:)if the modal can be swiped away. - Use
isBeingDismissedinsideviewDidDisappear(_:)when the presented controller needs self-cleanup. - Set delegates before presentation and keep them
weak. - Distinguish modal dismissal from navigation-stack removal.

