Search code examples
macosswiftcocoanssplitview

NSSplitViewController Child View Not Added


I've created a simple NSViewController and want to add a split view with just one child view. The split view should be controlled by a NSSplitViewController, because I'd like to use the NSSplitItem's facilities for collapsing/expanding split items. After adding a child view controller, the split item is created, but no child view is added to the view tree.

override func viewDidLoad() {
    super.viewDidLoad()
    let splitViewController = NSSplitViewController()
    view.addSubview(splitViewController.splitView)

    let myController = MyController(nibName: "MyController", bundle: nil)
    splitViewController.addChildViewController(myController)

    printTree(view)
}

func printTree(view: AnyObject, _ n: Int = 1) {
    if let view = view as? NSView {
        NSLog("\(n): \(view)")
        for child in view.subviews {
            printTree(child, n + 1)
        }
    }
}

Output:

1: <NSView: 0x618000120140>
2: <NSSplitView: 0x6180001205a0>

Why does the split view have no child view?


To compare, here's the version without split view:

override func viewDidLoad() {
    super.viewDidLoad()
    let myController = MyController(nibName: "MyController", bundle: nil)
    view.addSubview(myController.view)
    printTree(view)
}

Output:

1: <NSView: 0x6100001203c0>
2: <NSView: 0x6000001208c0>  <-- here's my child view
3: <NSButton: 0x600000140580>

And adding the child view directly as a subview to the split view doesn't work either:

A SplitView managed by a SplitViewController cannot have its subviews modified

So, my question is, why is the child view not added to the view tree inside the split view?


Solution

  • I figured it out. My mistake was that I added the splitView instead of the view:

    // this won't work:
    self.view.addSubview(splitViewController.splitView)
    
    // this will work:
    self.view.addSubview(splitViewController.view)
    

    BTW: using splitViewController.addChildViewController(myController) as I did before is just a shorter way of saying the following:

    let item = NSSplitViewItem(viewController: myController)
    splitViewController.addSplitViewItem(item)
    

    which didn't work for me because of my mistake described above.