Detecting sheet was dismissed on iOS 13
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
On iOS 13, many modal presentations became card-like sheets that users can dismiss with a swipe. That changed an important assumption: dismissal is no longer always controlled by a button that you own. If you need to know when the sheet was dismissed, the right tool is usually UIAdaptivePresentationControllerDelegate, not only viewDidDisappear.
Why iOS 13 Made This Matter
Before iOS 13, many modals were full-screen by default, so dismissal was often entirely under your control. With sheet presentation styles, users can drag the sheet down interactively. That means your code needs a callback that fires when the system completes that dismissal.
Use presentationControllerDidDismiss
The most direct callback is presentationControllerDidDismiss(_:).
Example in Swift:
If the user swipes the sheet down and the dismissal completes, this delegate method is called.
That is the usual answer when the requirement is specifically “tell me when the sheet was dismissed.”
Set the Delegate on the Presented Controller
A common source of confusion is where to assign the delegate. The presented view controller usually sets:
If you want the presenting controller to observe the dismissal instead, you can assign the presented controller’s presentationController?.delegate to the presenting controller after presentation setup, as long as the delegate object conforms correctly.
The key is that the delegate belongs to the UIPresentationController, not to a random view controller lifecycle event.
Related Delegate Methods
UIAdaptivePresentationControllerDelegate provides more than one callback. The most useful ones are:
- '
presentationControllerShouldDismiss' - '
presentationControllerWillDismiss' - '
presentationControllerDidDismiss' - '
presentationControllerDidAttemptToDismiss'
Example:
This is useful when the sheet contains a form and you want to block dismissal until the user confirms.
Difference Between Programmatic and Interactive Dismissal
If you dismiss the sheet yourself with:
then you may also use the dismissal completion handler on the presenting side or your own custom flow logic. But for user-driven swipe dismissal, the presentation controller delegate is the more specific and reliable signal.
That is why relying only on button actions is incomplete in iOS 13 style modal sheets.
What About viewDidDisappear
viewDidDisappear can tell you the view is no longer visible, but it is less precise. A view can disappear for reasons other than a completed sheet dismissal. For example, another presentation or navigation event could also cause it.
So while this works:
it does not answer the question as precisely as presentationControllerDidDismiss.
Use viewDidDisappear for general lifecycle work, and the presentation controller delegate when the dismissal event itself matters.
Complete Example With a Presenting Controller
The exact assignment timing can vary depending on your presentation flow, but the pattern is the same: attach the delegate and react in presentationControllerDidDismiss.
Common Pitfalls
The biggest pitfall is relying only on a close button callback. On iOS 13 sheets, users can often dismiss by swiping, so button-only logic misses a real path.
Another common mistake is expecting viewWillDisappear or viewDidDisappear to mean exactly “the sheet was dismissed by the user.” Those methods are broader lifecycle signals.
People also sometimes forget to set the presentation controller delegate, then wonder why none of the sheet callbacks fire.
Finally, if you block dismissal with presentationControllerShouldDismiss, remember to handle the user’s attempted swipe with presentationControllerDidAttemptToDismiss so the UI still gives feedback.
Summary
- For iOS 13 sheet dismissal detection, use
UIAdaptivePresentationControllerDelegate. - '
presentationControllerDidDismissis the key callback for completed dismissal.' - Set the delegate on the relevant
presentationController. - Use
presentationControllerShouldDismissandpresentationControllerDidAttemptToDismisswhen dismissal may be blocked. - '
viewDidDisappearis broader lifecycle information, not the most precise sheet-dismissal signal.'

