2017-04-18 222 views
0

我有一个视图控制器(包含我的菜单)呈现在另一个视图控制器(我的应用程序)的顶部。从所呈现的视图控制器访问呈现视图控制器?

我需要从提供的视图控制器(我的菜单)访问呈现视图控制器(在我的菜单下),例如访问一些变量或使呈现视图控制器执行其中一个segues。

但是,我只是不知道该怎么做。 我知道“presentsViewController”和“presentedViewController”变量,但我没有设法成功地使用它们。

任何想法?

代码(从所呈现的VC,其作为对AppDelegate中的参考,其中所述窗口被引用):

if let presentingViewController = 
    self.appDelegate.window?.rootViewController?.presentingViewController 
    { 
     presentingViewController.performSegue(
      withIdentifier: "nameOfMySegue", sender: self) 
    } 
+2

解决此问题的常用模式是使用委托设计模式。在你的Menu VC中声明一个委托,并将第一个VC设置为委托。现在你可以在代理上设置一个属性或一个调用方法。另一种方式可能是使用通知模式。 – TheAppMentor

+1

@TheAppMentor通过直接引用呈现的视图控制器来描述两种更好的设计模式。然而,如果你想要一个强耦合的关系,Apple确实会提供'presentationViewController'。 – dmorrow

+0

这两种方法实际上都有效。非常感谢。 – BUZZE

回答

4

以下是使用代理设计模式与呈现视图控制器进行对话的方式。

首先声明一个协议,列出委托人预期会响应的所有变量和方法。

protocol SomeProtocol { 

    var someVariable : String {get set} 

    func doSomething() 
} 

下一步:使您的演示视图控制器符合协议。 设置您呈现VC为代表

class MainVC: UIViewController, SomeProtocol { 

    var someVariable: String = "" 

    func doSomething() { 
     // Implementation of do 
    } 

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
     // Your code goes here. 

     if let destVC = segue.destination as? SubVC{ 
      destVC.delegate = self 
     } 
    } 

} 

最后,当您准备呼吁呈现VC(代表)的方法。

class SubVC: UIViewController { 
    var delegate : SomeProtocol? 


    func whenSomeEventHappens() { 

     // For eg : When a menu item is selected 

     // Set some Variable 
     delegate?.someVariable = "Some Value" 

     // Call a method on the deleate 
     delegate?.doSomething() 
    } 

} 
2

假设VCApplication正在呈现VCMenu,在VCMenu可以用访问VCApplication:

weak let vcApplication = self.presentingViewController as? VCApplicationType 

您的示例self.appDelegate.window?.rootViewController?.presentingViewController正在寻找显示rootViewController的ViewController - 它将是nil

编辑TheAppMentor我已经添加weak所以没有保留周期。

+1

虽然这种方法可行,但这会导致强烈的参考周期。这是因为,你现在有一个提交VC的菜单VC和菜单VC,并持有一个对演示VC的引用。 – TheAppMentor

+0

它的工作!非常感谢。 看来,你不能在呈现vc上执行segue,而呈现的vc尚未解除。 您必须首先解除所呈现的视图,然后调用segue。我结束了: 自我。解除(动画:真,完成:无) 如果让VC = self.presentingViewController呈现为? PresentingVCType { presentingVC.performSegue(withIdentifier:“nameOfMySegue”,sender:self) } – BUZZE