无法通过编程方式检测弹出窗口解除。

3

我想要在代码中关闭弹出视图控制器。如何检测到该事件并将值从弹出视图发送到主视图控制器?需要注意,当以编程方式关闭弹出视图时,popoverPresentationControllerDidDismissPopover方法无效。

有什么建议吗?

这是我的主视图控制器代码:

    let addFriendsPopoverViewController = storyboard?.instantiateViewControllerWithIdentifier("HomeEmotionPopOver") as! EmotionPopOverViewController
    addFriendsPopoverViewController.modalInPopover = true
    addFriendsPopoverViewController.modalPresentationStyle =   UIModalPresentationStyle.Popover
    addFriendsPopoverViewController.preferredContentSize = CGSizeMake(100, 100)
    let popoverMenuViewController = addFriendsPopoverViewController.popoverPresentationController
    popoverMenuViewController!.permittedArrowDirections = .Any
    popoverMenuViewController!.delegate = self
    popoverMenuViewController!.sourceView = self.view
    let height = (self.tableView.rowHeight - HeartAttributes.heartSize / 2.0 - 10) + (self.tableView.rowHeight * CGFloat((sender.view?.tag)!)) - 50
    popoverMenuViewController!.sourceRect = CGRect(
        x: 30,
        y: height,
        width: 1,
        height: 1)
    presentViewController(
        addFriendsPopoverViewController,
        animated: true,
        completion: nil)   

在弹出视图控制器中,我通过一个按钮的IBAction来关闭它:
     @IBAction func dismissPop(sender: AnyObject) {
    self.dismissViewControllerAnimated(true, completion: nil)

}

请发布您的代码,以便能够重现您的问题。 - pedrouan
我刚刚编辑了我的帖子,谢谢你的帮助。 - Marc Ibrahim
关闭弹出窗口的按钮是否在弹出窗口内部工作? - pedrouan
是的,没错。但我无法从主视图控制器中检测到它。 - Marc Ibrahim
我本想回答,但看到ColdLogic已经更快了,所以作罢。那正是你需要的。 - pedrouan
没问题,不过还是谢谢你! - Marc Ibrahim
2个回答

2
您的问题是想要在主视图控制器上找到一个函数,当弹出窗口关闭时调用该函数。技术上来说,这个函数是通过 viewDidAppear(animated:) 实现的。然而,这并不是完美的解决方案。如果您的弹出窗口没有覆盖整个屏幕,这个函数就不会触发,因此它是不可靠的解决方案。
实际上,您需要做的是从弹出窗口调用一个函数,通知主视图控制器已经完成/关闭。这可以通过委托协议轻松实现。
protocol PopoverDelegate {
    func popoverDismissed()
}

class PopoverViewController {
    weak var delegate: PopoverDelegate?

    //Your Popover View Controller Code
}

将协议符合性添加到您的主视图控制器中。
class MainViewController: UIViewController, PopoverDelegate {
     //Main View Controller code
}

然后你需要将弹出窗口的代理设置为主视图控制器。
let addFriendsPopoverViewController = storyboard?.instantiateViewControllerWithIdentifier("HomeEmotionPopOver") as! EmotionPopOverViewController
addFriendsPopoverViewController.delegate = self
//The rest of your code

最后,在您关闭弹出窗口视图控制器时,请从该代理函数中调用此函数。
@IBAction func dismissPop(sender: AnyObject) {
     dismissViewControllerAnimated(true, completion: nil)
     delegate?.popoverDismissed()
}

在您的主视图控制器中,实现委托方法。
func popoverDismissed() {
    //Any code to run when popover is dismissed
}

谢谢您的快速回答,但是我无法将弹出窗口的代理设置为主视图控制器。我收到了一个错误:无法将代理分配给主视图控制器... - Marc Ibrahim
你是否已将协议一致性添加到主视图控制器中?我在我的答案中添加了示例代码以展示如何实现。 - ColdLogic
非常感谢!您认为我应该如何将变量值从弹出窗口发送到主窗口? - Marc Ibrahim
您可以修改 popoverDismissed 函数以传递变量。例如:func popoverDismissed(selectedString: String)。这个变量显然不需要是字符串,但这是一个例子。 - ColdLogic

1
关键是要自己解除转场,但让它看起来像是用户发起的,这样可以通过委托方法popoverPresentationControllerDidDismissPopover()检测到。
我通过向presentingViewController的dismiss()函数添加完成闭包并直接调用该程序来实现。
if let pvc = self.presentingViewController {
    var didDismiss : ((UIPopoverPresentationController) -> Void)? = nil
    if let delegate = popoverPresentationController?.delegate {
        // check it is okay to dismiss the popover
        let okayToDismiss = delegate.popoverPresentationControllerShouldDismissPopover?(popoverPresentationController!) ?? true
        if okayToDismiss {
            // create completion closure
            didDismiss = delegate.popoverPresentationControllerDidDismissPopover
        }
    }
    // use local var to avoid memory leaks
    let ppc = popoverPresentationController
    // dismiss popover with completion closure
    pvc.dismiss(animated: true) {
        didDismiss?(ppc!)
    }
}

对我来说它正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接