Swift: Popover rejects callback

There are two UIViewConrollers in my storyboard: MainViewController and SecondViewController . I am going to show SecondViewController as a popover when the user clicks the Show Popover button:

enter image description here

//MainViewController override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "GoToSecondViewControllerSegue" { var vc = segue.destinationViewController as! SecondViewController var controller = vc.popoverPresentationController if controller != nil { controller?.delegate = self vc.inputTextDelegate = "I'm a popover!" } } } func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) { println("done") } func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle { return .None } 

 //SecondViewController @IBAction func dismissPopover(sender: UIButton) { dismissViewControllerAnimated(true, completion: nil) //This dismisses the popover but does not notify the MainViewConroller } 

The segue anchor is connected to the button: enter image description here

Now I have two problems:

  • When I click the cancel button inside the popover, it rejects the popover but does not call the popoverPresentationControllerDidDismissPopover inside the MainViewController

  • How to transfer data from SecondViewController to MainViewController , text value of UITextView, for example.

+7
source share
4 answers

Protocols and delegations are the solution to such problems. In my case, I defined the protocol and matched the MainViewController for the protocol.

 //SecondViewController protocol MyDelegate{ func DoSomething(text:String) } class SecondViewController: UIViewController { var delegate:GetTextDelegate? var inputTextDelegate:String = "" override func viewDidLoad() { newText.text = inputTextDelegate } @IBAction func dismissPopover(sender: UIButton) { dismissViewControllerAnimated(true, completion: nil) //This dismisses the popover but does not notify the MainViewConroller } @IBAction func doneButtonAction(sender: UIButton) { if let delegate = self.delegate { delegate.DoSomething(newText.text) self.dismissViewControllerAnimated(true, completion: nil) } } } 

 class MainViewController: UIViewController, UIPopoverPresentationControllerDelegate, MyDelegate { override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "GoToSecondViewControllerSegue" { var vc = segue.destinationViewController as! SecondViewController vc.delegate = self vc.inputTextDelegate = "I'm a popover!" } } func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) { //... } func DoSomething(text: String) { //Do whatever you want println(text) } } 
+8
source

Or, simply put, just call the iOS delegate method manually when you reject the popover manually.

  dismissViewControllerAnimated(true, completion: nil) popoverPresentationController?.delegate?.popoverPresentationControllerDidDismissPopover?(popoverPresentationController!) 
+11
source

You must set yourself as popOverDelegate. You must do this at the destination popoverPresentationController.

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { segue.destination.popoverPresentationController?.delegate = self } 

Then declare the delegate implementation in your ViewController:

 extension FormViewController: UIPopoverPresentationControllerDelegate { func popoverPresentationControllerDidDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) { printBreadcrumb("Dismissed popover") } } 
+9
source

I have the same problem and find the answer in the Apple API .

About the popoverPresentationControllerDidDismissPopover function, say The popover presentation controller calls this method after dismissing the popover to let you know that it is no longer onscreen. The presentation controller calls this method only in response to user actions. It does not call this method if you dismiss the popover programmatically. The popover presentation controller calls this method after dismissing the popover to let you know that it is no longer onscreen. The presentation controller calls this method only in response to user actions. It does not call this method if you dismiss the popover programmatically.

So we have to do it ourselves.

You can choose a block or delegate like @Maysam, which was heavier. Here is my way to use the FYI block.

Let's just focus on key features.

 class SecondViewController: UIViewController { var dismissPopover: (() -> Void)? deinit { if let block = self.dismissPopover { block() } } @IBAction func dismissPopover(sender: UIButton) { dismissViewControllerAnimated(true, completion: nil) //This dismisses the popover but does not notify the MainViewConroller } } 

I made a block and called it wellVin deinit.

 class MainViewController: UIViewController, UIPopoverPresentationControllerDelegate, MyDelegate { override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "GoToSecondViewControllerSegue" { var vc = segue.destinationViewController as! SecondViewController vc..dismissPopover = { [unowned self] () in self.DoSomehing() // call your method... } } } func DoSomething(text: String) { //Do whatever you want println(text) } } 

Configure the block in the prepareForSegue: method and Done file.

-1
source

Source: https://habr.com/ru/post/976799/


All Articles