Move to a view controller on click of a button inside UIPopoverPresentationController

718 Views Asked by At

I have a table view controller with a cell that has a button.

On click of this button I am displaying a view controller as an UIPopoverPresentationController.

This pop over controller has two buttons , YES and NO.

On click of YES I want to be able to segue to another view controller and on click of NO I will dismiss the pop over controller.

On click of NO the popover gets dismissed but on click of YES I don't move to the required view controller .

Although the view did load() method of that view controller gets called. The problem is that the new view controller is not being displayed.

On click of YES,the popover gets dismissed but remains on the previous view controller

Following is my code

TableViewController class

func onTapPickButton(sender: UIButton) { 

 let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil) 
        let popoverViewController = storyboard.instantiateViewController(withIdentifier: "ConfirmDialogViewController") as! ConfirmDialogViewController 
        popoverViewController.preferredContentSize = CGSize(width: view.frame.width/1.33, height: view.frame.height/2.34) 
        popoverViewController.modalPresentationStyle = UIModalPresentationStyle.popover 
        let popover: UIPopoverPresentationController = popoverViewController.popoverPresentationController! 
        popover.sourceView = self.view 
        popover.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)         
        popover.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0) 
        popover.delegate = self 

        present(popoverViewController, animated: true, completion: nil) 
}

PopOver View controller class

@IBAction func onTapNoButton(_ sender: UIButton) { 
        self.dismiss(animated: true, completion: {}) 
    } 

    @IBAction func onTapYesButton(_ sender: UIButton) { 
        let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let viewController = storyboard.instantiateViewController(withIdentifier: "View") as! ViewController
present(viewController, animated: true, completion: nil)

    } 

Any help will be appreciated. Thank you.

2

There are 2 best solutions below

1
Amal T S On

In YES button action, dismiss the popOver and in completion block present the new viewController

 @IBAction func onTapYesButton(_ sender: UIButton) { 
                let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                let viewController = storyboard.instantiateViewController(withIdentifier: "View") as! ViewController
                self.dismiss(animated: true, completion: {
                       self.present(viewController, animated: true, completion: nil)
                }) 

            } 
0
Lawliet On

You can create either a closure (completion handler) or delegate to catch when 'YES' button was selected. These would be useful in case you ever want to capture any data from the Popover ViewController. For example:

Completion handler:

class ConfirmDialogViewController: UIViewController {
    open var didSelectYesHandler: ((_ selectedData: String) -> ())?

    public init(for sender: UIView, didSelectYesHandler: ((_ selectedData: String) -> ())? = nil) {
        super.init(nibName: nil, bundle: nil)

        modalPresentationStyle = .popover
        self.sender = sender
        self.didSelectDataHandler = didSelectDataHandler

        guard let popoverPC = popoverPresentationController else { return }
        popoverPC.sourceView = sender
        popoverPC.sourceRect = sender.bounds
        popoverPC.delegate = self
    }

    @IBAction func onTapYesButton(_ sender: UIButton) { 
        dismiss(animated: true, completion: nil)
        didSelectDataHandler?("YES")
    }

    // MARK: - PopoverPC Delegate Methods

    func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
        return UIModalPresentationStyle.none
    }
}

Delegate:

protocol ConfirmDialogViewControllerDelegate: class {
    func didSelectYes(_ selectedDate: String)
}

class ConfirmDialogViewController: UIViewController {
    weak var delegate: ConfirmDialogViewControllerDelegate?

    @IBAction func onTapYesButton(_ sender: UIButton) { 
        dismiss(animated: true, completion: nil)
        delegate?.didSelectData("YES")
    } 
}

// In your current view controller set 
popoverViewController.delegate = self

Bonus:

Check out this library if you want to have a popover containing a data list for selection.