Swift: 弹出窗口关闭回调

Swift: Popover dismiss callback

我的 Storyboard 中有两个 UIViewConrollerMainViewControllerSecondViewController。我将在用户点击名为 Show Popover:

的按钮时将 SecondViewController 显示为弹出窗口

//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
}

segue 的锚点连接到一个按钮:

现在我有两个问题:

  1. 当我点击弹出窗口内的取消按钮时,它会关闭弹出窗口但不会触发 MainViewController

    内的 popoverPresentationControllerDidDismissPopover
  2. 如何将数据从 SecondViewController 传递到 MainViewController,例如 UITextView 的文本值。

协议和授权是解决此类问题的方法。在我的例子中,我定义了一个协议并使 MainViewController 符合该协议。

//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)
 }

}

我有同样的问题,在Apple API中找到了答案。

关于函数popoverPresentationControllerDidDismissPopover,他们说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.

所以我们必须自己做。

您可以像@Maysam 那样选择更重的块或委托。 这是我使用块的方式,仅供参考。

我们只关注关键功能。

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
 }
}

我做了一个block,好好调用secondVC 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)
 }

}

在 prepareForSegue: 方法中设置块,然后完成。

或者,更简单地说,当您手动关闭弹出窗口时,只需手动调用 iOS 的委托方法。

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

您需要将自己设置为popOverDelegate。您必须在目标的 popoverPresentationController 中执行此操作。

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

然后在您的 ViewController:

中声明实现委托
extension FormViewController: UIPopoverPresentationControllerDelegate {

    func popoverPresentationControllerDidDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) {
        printBreadcrumb("Dismissed popover")
    }

}