Aperture Plugin: Using Bindings To Populate The Length Pop-Up
2007-02-20

To populate the length pop-up I'm going to use bindings. Bindings allow changes in one object to automatically control another object. In this case I want the contents of the length pop-up to reflect the values I store in an array in my Random_Wok instance. Each time I change the array contents, the pop-up contents change. The advantage to this is that I don't have to write the code that populates the pop-up.
To make this work I need a third object: an array controller instance in my nib. An array controller is a pre-written, general-purpose controller that knows how to communicate with objects that expose bindings. It's like hiring a manager to run a department. Since it knows about arrays it can take a lot of work off my hands by dealing with the individual array elements for me. The array controller will mediate between changes in my data model and updates to the view.
To get an array controller instance into my nib I drag one from the controller palette to the nib file:

And I give it a name by double-clicking it: Length Popup Controller. To make the controller do anything useful I have to hook it up to a data model (an array) and a view (the pop-up). The controller then mediates between these for me.
The first thing I have to do is tell the controller what kind of object is in the array it is dealing with. "Good morning new manager, your staff consists of interns". In this case it is an array of NSMutableStrings that I will be modifying according to which string lengths I want the user to be able to choose:

Then I have to tell the array controller which array it will be dealing with. "Your interns are in that cube farm over there". To do this I bind the array controllers content array to the array of length strings in my Random_Wok object. That's an ivar called _lengthStrings:

I bind to File's Owner because that is a stand-in for my Random_Wok class. What this step does is to make the controller able to observe changes to the _lengthStrings array. The observation is incomplete at this stage -- the manager knows which cube farm to keep an eye on, but none of the interns yet know to tell the manager that anything has happened.
Next I have to tell the pop-up button that its contents will be supplied by an array controller. To do that I select the pop-up button and bind it to the array controller. The pop-up button has a binding called content that is designed for doing just this:

The controller key (arrangedObjects) is what the pop-up will observe to get its content. "Catering department, watch the manager's list of foods on his white board. Any time he changes it update the menu".
The last thing I must do is to add code to Random_Wok so that the object tells the NSArrayController that something has changed (remember that the interns in their cubes don't automatically tell the manager that their choice of foods has been updated). I code manual observer notification for this by using -willChangeValueForKey: and -didChangeValueForKey:

I need this manual method of notifying the controller that something has happened because my Random_Wok class is not Key Value Observing compliant. As a class it lacks the methods that the KVO mechanism requires to have change notifications automatically sent to observers. The array controller is KVO compliant, to the pop-up can automatically get notifications that the content array has changed.
Now the interns are saying to the manager "We will have a new list of foods in a minute -- OK, it's been updated". And the manager knows to update his whiteboard, the caterers see the new list of foods because they are watching the whiteboard, and the menu gets changed. And all along the interns don't know or care why they are creating food lists, and the caterers don't know or care where the food lists are coming from.
I try out the code and it works:

The final code for actually creating the array was more complicated than the little test I initially wrote:

This includes some extra logic to select the current length, or if not possible, use the highest length available. In this way as the user clicks around the available controls the pop-up does not keep resetting to the minimum length setting.
The other parts of this series can be found via the Cocoa page.
The Bagelturf site welcomes Donations of any size