Learn Objective-C on the Mac - Mark Dalrymple [64]
The next thing you have to do is configure a binding, not for a GUI object, but for the array controller itself! It just so happens that NSArrayController is not only a “provider” of bindings-ready access to model objects. It’s a “consumer” as well, retrieving its content array from another object via Cocoa Bindings. In our case, it will get its content from DungeonThingAppDelegate’s characters array. With the array controller still selected, bring up the Bindings Inspector (⌘4). Click on the disclosure triangle next to Content Array to open it up, and set up the desired binding by choosing “App Controller” from the popup list, typing “characters” into the Model Key Path field, and pressing Enter. Note that our DungeonThingAppDelegate required no special preparation in order to be “bindings-friendly.” All we have to do is expose an instance variable as a property (as we’ve done for our three content arrays), and we can immediately use it to bind other objects to!
Now we’ve added an NSArrayController and configured it to access the right data from our DungeonThingAppDelegate. It’s time to bind some GUI objects to this new controller.
Bind Table Display via the Array Controller
First we’ll set up a single binding for the table view. In fact, it’s not the table view but the table column itself that needs a binding. We’re going to bind the table column’s displayed value to the characters array (through the array controller), grabbing the timestamp attribute from each model object. Here’s how: click on the table column until it’s selected, then open the Value binding configuration section in the Bindings Inspector. Choose “characters” from the popup list, then “arrangedObjects” in the Controller Key combo box, then “timestamp” in the Model Key Path, and click the Bind checkbox. We mentioned earlier that the Controller Key combo box lets you choose different aspects of the controller object you’re binding through. In this case, binding through “arrangedObjects” means that we’re binding to the entire sorted array of objects. This sort of binding is usually only appropriate for view objects that can display an entire array of content, such as a table column. Choosing “timestamp” for the Model Key Path tells the table column which value it should pull from each model object it gets access to.
Bind a Text Field via the Array Controller’s Selection
The final binding that needs to be done for the characters section is for the text field that displays the value. This binding will also be done through the array controller, grabbing the createdObject attribute from the controller’s selected object.
Click to select the text field in the box on the left. Your first click probably selects the box itself, and clicking again will then select the text field. Now look again at the Bindings Inspector, and find the Value binding configuration. Select “characters” from the popup list, “selection” from the Controller Key combo box, and “createdObject” from the Model Key Path combo box, then click to turn on the Bind checkbox. Note that by choosing “selection” for the Controller Key, we specify that the array controller will only make the selected object available to this control, rather than a whole array of them as it does with the table column.
Making Sure it Works
Now switch back to Xcode, and build and run your application. You should be able to create a new character, and see it appear in the text field along with a timestamp entry in the table below. Modify some preferences, then make another character, and you should see the new parameter summary in the text field, and a new timestamp in the table view. Switch between the rows by clicking on them, and you should see the value in the text field change accordingly.
If any of those things don’t work, go back to Interface Builder and double-check the configuration of your bindings, as well as DungeonThingAppDelegate’s connection