12
votes

I'm updating an app to use universal storyboards. I've created a popover segue to a new viewcontroller using interface builder by dragging from a button to my new viewcontroller and selecting 'Present As Popover' as the kind of segue.

When the user presses outside of the popover (dismissing it) I need to be notified in the presenting view controller so I can undo their actions. How can I do this?

Normally I would have created the popover manually and made my viewcontroller the popover's delegate; allowing me to use the popoverControllerDidDismissPopover delegate call back. However, this is deprecated in iOS9 and even if it wasn't I've no idea where to find the popover so I can set its delegate to my view controller.

4

4 Answers

13
votes

Not sure which method you're referring to as being deprecated but you can still use the UIPopoverPresentationControllerDelegate to achieve this. Something like:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "popoverSegue" {
        let vc = segue.destinationViewController
        sortVC.modalPresentationStyle = .Popover
        sortVC.popoverPresentationController?.sourceRect = filterButton.bounds
        sortVC.preferredContentSize = CGSizeMake(216, 150)
        sortVC.popoverPresentationController!.delegate = self
    }
}

And then use the

func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController)

method to handle its dismissal.

9
votes

The popoverControllerDidDismissPopover: method has been replaced by popoverPresentationControllerShouldDismissPopover: because UIPopoverControllerDelegate has been replaced by the UIPopoverPresentationControllerDelegate.

From your presenting view controller, conform to the new protocol and set the delegate for the popover presentation controller in prepareForSegue::

class MyPresentingViewController: UIViewController, UIPopoverPresentationControllerDelegate {

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {         
        if let popoverPresentationController = segue.destinationViewController.popoverPresentationController {
            popoverPresentationController.delegate = self
        }
    }

    func popoverPresentationControllerShouldDismissPopover(popoverPresentationController: UIPopoverPresentationController) -> Bool {
        return true
    }
}

You can then use the delegate method to handle detection of the dismissal in the way that you were previously intending.

1
votes

The updated answer for this issue.

All credit to this answer:

The method you must use on iOS 13: - (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController

1
votes

The UIPopoverPresentationControllerDelegate inherits from UIAdaptivePresentationControllerDelegate which contains the presentationControllerShouldDismiss and presentationControllerDidDismiss as Beto points out.

I simply moved the code I had in the popover versions of these functions to UIAdaptivePresentationControllerDelegate version and they work exactly the same as before.

Did not have to change the delegate declarations on the view controller or set isModalInPresentation.

The original code still worked under 13.2.3 but those function are depreciated and one day they will stop working...or not?

my app is an iPad app using popovers and not presentation sheets or card styles.