Accessing methods, actions and/or outlets from oth

2019-09-19 09:30发布

问题:

I'm working on a macOS project where I have a split view containing 2 other ViewControllers and I can't figure out how to access the ViewControllers from my primary window's ViewController.

this is the setup:

Basically what I'm trying to do is use the Button in my ViewController on the top-left to access the Label in my SectionController on the right, which is embedded in my split view.

Since I can't create an IBAction or IBOutlet for a control in a different ViewController, I can't figure out how to get these to be connected. My current workaround has been to have a property on my AppDelegate and then access the main shared application delegate, but that feels hacky and won't scale. I'm completely lost as to how to proceed. I'm ok with using a function to pass data or whatever to the other ViewController(s).

I'm using Swift 4 with Xcode 9 (beta).

Any ideas?

回答1:

Of course you can't create IBAction or IBOutlet for a control in a different ViewController!! But simply each view controller in the hierarchy has a reference for its child view controllers.

Method 1:

@IBAction func buttonTapped(_ sender: Any) {
    let splitViewController = self.childViewControllers[0] as! YourSplitViewController
    let targetViewController = splitViewController.childViewControllers[0] as! YourTargetViewController
    targetViewController.label.text = "Whatever!"
}

Method 2:

It may be better if you took a reference for each child controller in your "prepare for segue" method

ContainerViewController:

var mySplitViewController: YourSplitViewController?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "splitViewSegue" {
        self.mySplitViewController = segue.destination as! YourSplitViewController
    }
}

YourSplitViewController:

var aViewController: YourFirstViewController?
var bViewController: YourSecondViewController?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "aViewSegue" {
        self.aViewController = segue.destination as! YourFirstViewController
    } else if segue.identifier == "bViewSegue" {
        self.bViewController = segue.destination as! YourSecondViewController
    }
}

So you can access it like that in your container view controller:

@IBAction func buttonTapped(_ sender: Any) {
    self.mySplitViewController.firstViewController.label.text = "Whatever!"
}