It is possible in some cases (iPhone X, iOS 13) to dismiss presented view controllers with a gesture, by pulling from the top.
In that case, I can't seem to find a way to notify the presenting view controller. Did I miss something?
The only I found would be to add a delegate method to the viewDidDisappear of the presented view controller.
Something like:
class Presenting: UIViewController, PresentedDelegate {
func someAction() {
let presented = Presented()
presented.delegate = self
present(presented, animated: true, completion: nil)
}
func presentedDidDismiss(_ presented: Presented) {
// Presented was dismissed
}
}
protocol PresentedDelegate: AnyObject {
func presentedDidDismiss(_ presented: Presented)
}
class Presented: UIViewController {
weak var delegate: PresentedDelegate?
override func viewDidDisappear(animated: Bool) {
...
delegate?.presentedDidDismiss(self)
}
}
It is also possible to manage this via notifications, using a vc subclass but it is still not satisfactory.
extension Notification.Name {
static let viewControllerDidDisappear = Notification.Name("UIViewController.viewControllerDidDisappear")
}
open class NotifyingViewController: UIViewController {
override open func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NotificationCenter.default.post(name: .viewControllerDidDisappear, object: self)
}
}
There must be a better way to do this?
It is an array of views in the interface behind the popover; the user can interact with these views, but a tap anywhere else outside the popover will dismiss it (with no effect on the thing tapped). If passThroughViews is nil, a tap anywhere outside the popover will dismiss it.
The UIViewController class defines the shared behavior that's common to all view controllers. You rarely create instances of the UIViewController class directly. Instead, you subclass UIViewController and add the methods and properties needed to manage the view controller's view hierarchy.
From iOS 13 Apple has introduced a new way for the users to dismiss
the presented view controller by pulling it down from the top. This event can be captured by implementing the UIAdaptivePresentationControllerDelegate
to the UIViewController
you're presenting on, in this case, the Presenting
controller. And then you can get notified about this event in the method presentationControllerDidDismiss
. Here is the code example :-
class Presenting: UIViewController, UIAdaptivePresentationControllerDelegate {
func someAction() {
let presented = Presented()
presented.presentationController?.delegate = self
present(presented, animated: true, completion: nil)
}
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
// Only called when the sheet is dismissed by DRAGGING.
// You'll need something extra if you call .dismiss() on the child.
// (I found that overriding dismiss in the child and calling
// presentationController.delegate?.presentationControllerDidDismiss
// works well).
}
}
Note:
dismiss(animated:,completion:)
method. Notification
observer for getting the event where the user dismisses the controller by swiping down, so you can remove them. Adopt UIAdaptivePresentationControllerDelegate
and implement presentationControllerDidAttemptToDismiss
(iOS 13+)
extension Presenting : UIAdaptivePresentationControllerDelegate {
func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController) {
presentationController.presentingViewController.presentedDidDismiss(self)
}
}
UIPresentationController
has a property presentingViewController
. The name is self-explanatory. You don't need the explicit delegate protocol.
The method is actually called to be able to show a dialog for example to save changes before dismissing the controller. You can also implement presentationControllerDidDismiss()
And do not post notifications to controllers which are related to each other. That's bad practice.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With