1
votes

My attempts at getting something back from my UIPopoverPresentationController fails even after setting up a protocol and delegate.

I include both the custom delegate (SavingViewControllerDelegate) and UIPopoverPresentationControllerDelegate in my controller that will call the popover. The user will tap a UIBarButton which is calling a function in my controller. In the controller, I open the Popover programmatically:

        let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyboard.instantiateViewControllerWithIdentifier("PopoverProfileViewController") as! ProfileViewController
        vc.modalPresentationStyle = UIModalPresentationStyle.Popover
        let popover: UIPopoverPresentationController = vc.popoverPresentationController!
        popover.barButtonItem = sender as? UIBarButtonItem
        popover.delegate = self
        self.presentViewController(vc, animated: true, completion:nil)

in this view controller, I have this function

func sendLoginStatus(status : Bool) {
    print("LoginStatus")
    print(status)
}

In the popover's view controller, I added a protocol:

protocol SavingViewControllerDelegate
{
    func sendLoginStatus(status : Bool)
}

I also added a breakout at func sendLoginStatus(status : Bool), which returns "delegate SavingViewControllerDelegate? Some".

In ProfileViewController:

class ProfileViewController: UIViewController {
    var delegate : SavingViewControllerDelegate?

When the user taps a button, a bool value should be send back to the calling controller.

@IBAction func logoutButton(sender: AnyObject) {
    print("sendStatus")
    delegate?.sendLoginStatus(true)
    dismissViewControllerAnimated(true, completion: nil)
}

I added a breakpoint at delegate?.sendLoginStatus(true), which returns that "delegate SavingViewControllerDelegate?" is nil. sendLoginStatus is never called.

1

1 Answers

2
votes

You used a delegate from UIPopoverPresentationController and expected results from your own protocol.

Instead of setting the popover delegate conforming to protocol UIPopoverPresentationControllerDelegate you should create a reference to your own delegate:

let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("PopoverProfileViewController") as! ProfileViewController

// Setting the SavingViewControllerDelegate
vc.delegate = self
vc.modalPresentationStyle = UIModalPresentationStyle.Popover

let popover: UIPopoverPresentationController = vc.popoverPresentationController!
popover.barButtonItem = sender as? UIBarButtonItem

// Setting the UIPopoverPresentationControllerDelegate
popover.delegate = self

self.presentViewController(vc, animated: true, completion:nil)

You can now use your own delegate functions and the UIPopoverPresentationController delegate functions:

extension YourClass : UIPopoverPresentationControllerDelegate {
    // All functions of the UIPopoverPresentationControllerDelegate you wish to use
}

extension YourClass : SavingViewControllerDelegate {
    func sendLoginStatus(status : Bool) {
        // Code
    }
}

Sidenote 1: to prevent a retain cycle of delegates I'd recommend a weak var delegate: SavingViewControllerDelegate? instead of just var ~~

Sidenote 2: It is common practice to also include a sender in delegate functions:

protocol SavingViewControllerDelegate {
    func sendLoginStatus(sender: ProfileViewController, status : Bool)
}