Instantiating split view controller by identifier

2019-08-12 17:58发布

问题:

I'm trying to implement a master-detail-detail view in a Swift OS X application. The top-level view controller is an NSSplitViewController with three subview controllers. The master and first detail views are fairly standard with fixed behaviors. The second detail view needs to change according to the selection in the first detail view.

The second detail controller is a simple view controller, which will respond to selection changes in the first detail view by installing a new subview and controller depending on the selection.

The alternate view controllers for the final content are implemented in the same storyboard, not connected to anything by segues; the intent is to create them with -[NSStoryboard instantiateControllerWithIdentifier:] and install them as child view controllers and subviews.

The instantiated view controllers happen to be NSSplitViewControllers.

Here's the problem: when I instantiate the detail split view controllers and install them, they are empty. What I have been able to observe so far is:

  • The instantiated view controllers are of the correct class (a subview of NSSplitViewController);
  • They have no subviews
  • They do have splitViewItems, and the splitViewItems are the view controllers I was expecting to see loaded

Is there something I need to do to fully load/populate the loaded split view controllers?

TIA, Doug

回答1:

Found it. I was trying add the instantiated NSSplitViewController's "splitView" as a subview, rather than its "view" (which contains the splitView). Accessing the "view" property loads the view hierarchy; using the "splitView" did not.



回答2:

If you add an split view controller to storyboard and delete the connections to the two provided split view items you might add them with addChildViewController: and you have to set Storyboard ID for those views

class SplitViewController: NSSplitViewController {

@IBOutlet weak var mySplitView: NSSplitView!

var leftPane: NSViewController?
var contentView: NSViewController?

override func viewDidLoad() {
    super.viewDidLoad()
    let story = self.storyboard

    leftPane = story?.instantiateController(withIdentifier: "LeftPaneViewController") as! LeftPaneViewController?
    contentView = story?.instantiateController(withIdentifier: "ContentViewController") as! ContentViewController?

    self.addChildViewController(leftPane!)
    self.addChildViewController(contentView!)
}

}


回答3:

In my case I was calling addSplitViewItem() in the NSSplitViewController subclass inside init?(coder:), which was too early. Once I moved the calls to viewDidLoad(), the view hierarchy of each spit view item's view controller was added to the split view controller's view heirarchy and everything worked correctly.