关闭呈现的视图控制器后调用主控制器的函数

Posted

技术标签:

【中文标题】关闭呈现的视图控制器后调用主控制器的函数【英文标题】:call a function of a maincontroller after a presented viewcontroller is dismissed 【发布时间】:2018-04-26 15:04:34 【问题描述】:

我有一个显示视图控制器的 MainViewcontroller。用户可能会采取一个动作,首先应该关闭视图控制器,然后调用 MainViewcontroller 中定义的函数。

约束是这个函数将创建一个新的vc来呈现。我试过主控制器的viewWillAppear和viewdidAppear。这不起作用,因为它们被多次调用。

我也可以使用通知机制,但我不确定 MainViewController 是否会在收到通知之前出现。

【问题讨论】:

viewWillAppear/viewDidAppear第一次运行后使用布尔值来检测是否应该调用该函数并将其设置为false。 【参考方案1】:

你应该看看presentingViewController document。从呈现的视图控制器中,您可以使用 self.presentingViewController 获取 MainViewController。在下面试试我的代码

let mainViewController = self.presentingViewController as! MainViewController

self.dismiss(animated: true) 
  mainViewController.doWhateverYouWant()

【讨论】:

这样做,确定执行闭包时mainViewController是可见的吗? 关闭将在视图控制器关闭后执行。这时候,mainViewController 是可见的。你可以试试看。 你的代码在打开一个可选参数时意外抛出了 nil 更新了我的答案,你可以再试一次。 我认为应该在要捕获的闭包之外定义mainviewcontroller。【参考方案2】:

具体解决方案

假设这是你的MainViewController

class MainViewController: UIViewController 

    func foo() 
        print("foo")
        

你可以像这样声明你的SecondViewController

class SecondViewController: UIViewController 

    @IBAction func didTapDismiss(_ sender: UIButton) 
        self.dismiss(animated: true, completion: nil)
    

    override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) 
        let mainViewController = self.presentingViewController as? MainViewController
        super.dismiss(animated: flag) 
            mainViewController?.foo()
            completion?()
        
    

如您所见,一旦 SecondViewController 被解除,mainViewController?.foo() 方法就会被调用。

一般解决方案

让我们定义MainViewController

class MainViewController: UIViewController 

    typealias CallBack = () -> Void

    func foo() 
        print("foo")
    

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
        if let mainViewControllerCallbackProtocol = segue.destination as? MainViewControllerCallbackProtocol 
            mainViewControllerCallbackProtocol.mainViewControllerCallback =  [weak self] in
                self?.foo()
            
        
    

还有自己的回调协议

protocol MainViewControllerCallbackProtocol:AnyObject 
    var mainViewControllerCallback: MainViewController.CallBack?  get set 

最后让我们将SecondViewController 统一为MainViewControllerCallbackProtocol

class SecondViewController: UIViewController, MainViewControllerCallbackProtocol 

    var mainViewControllerCallback: MainViewController.CallBack?

    @IBAction func didTapDismiss(_ sender: UIButton) 
        self.dismiss(animated: true, completion: nil)
    

    override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) 
        super.dismiss(animated: flag)  [weak self] in
            self?.mainViewControllerCallback?()
            completion?()
        
    

【讨论】:

以上是关于关闭呈现的视图控制器后调用主控制器的函数的主要内容,如果未能解决你的问题,请参考以下文章

如何在快速关闭呈现的控制器后推送控制器?

如何在不调用 [关闭] 的情况下将整数从控制器设置到子视图

如何从模态视图控制器调用呈现视图控制器的方法

呈现一个新的视图控制器然后关闭它,调用父视图控制器上的 init()

关闭模态视图控制器后呈现不同的视图控制器

关闭模态呈现的视图控制器后切换标签栏控制器视图控制器