NSplitViewController and Bindings

(Note: 1/11/16 — This all worked until I implemented saving and loading. Then, I think the problem is that the array controller gets bound to the data after it’s already read in. So far I haven’t been able to work around this problem)

I created a new project similar to my previous post, but used a split view as the parent class of ViewController. I took all the UI out of the corresponding XIB file. Then I subclassed NSViewController to create TopViewController and BottomViewController (created XIBs for each when I added them). TopViewController’s view looks like this:

TopViewControllerUI

And BottomViewController’s view:

BottomViewControllerUI

There is a new Object, Module:

@objc(Module)
class Module: NSObject {
	var name: String = "New Module"
	var active: Bool = true
}

And each Flow can now contain an array of Modules:

@objc(Flow)
class Flow: NSObject {
	var name: String = "New Flow"
	var active: Bool = true
	
	dynamic var modules: [Module] = []
}

The top view controller displays the flows and allows you to select one.
The bottom view controller displays the contained modules of the selected flow.

This brings up how to bind the bottom view controller’s array controller to the top view controller’s array controller’s selection. I don’t know how many ‘best practices’ I’m breaking here, but the way I did it was to add a property to store the top view controller in the bottom view controller.

class BottomViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.
    }
	override var nibName: String? {
		return "BottomViewController"
	}
	
	dynamic weak var topViewController: TopViewController?
}

The parent split view controller sets all this up:

lass ViewController: NSSplitViewController {
	
    override func viewDidLoad() {
        super.viewDidLoad()
		
		self.splitView.vertical = false
		
		topViewController = TopViewController()
		addChildViewController(topViewController!)
		
		bottomViewController = BottomViewController()
		bottomViewController!.topViewController = topViewController
		addChildViewController(bottomViewController!)
    }
 
	override var nibName: String? {
		return "ViewController"
	}
	
	dynamic var topViewController: TopViewController?
	dynamic var bottomViewController: BottomViewController?
}

The only thing really twisty about all of this is the binding of the bottom ArrayController’s ContentArray. This is as below:

BottomArrayControllerBinding

Here’s the thing running with some data added:

SplitViewApp

Leave a Reply

Your email address will not be published. Required fields are marked *