Clicker: My First Little Cocoa App
To work.A slider and a text field are bound together so that each reflects the other's value. A button labeled Click doubles the value in the text field.
I create a new project then locate the mainmenu.nib file to design the interface. I'm not yet certain what a nib file is. It is not a template, I know that, it contains "archived" objects: instances of objects that have been coded for storage in a file. And I know it contains all the goodies necessary for allowing the application create the user interface at run time. Or even before then: IB itself can "run" the interface, a little like Frankenstein's monster before it had a brain.
Creating the interface in Interface Builder is easy enough, just dragging in interface elements from the pallete onto the Wiindow object. I also drag in an NSObjectController because I want to control a single object, an instance of my custom class, Clicker. I remember enough of the tutorials (currency converter for instance) to create Clicker by going to the clases tab of my nib file and subclassing NSObject. From there I can instantiate it from the Classes menu. Now Clicker appears as a blue box on my nib file Instances tab.

I rename my NSObjectController to ClickerController so I know what it controls. I don't actually know why I need a NSObjectController for this, but that is the way things are done and I will persue this later.
The inspector in IB does not appear unless you pull it up from the Window menu -- pretty odd behavior because there is little you can do without it. Since I want the object controller to control Clicker with a binding, I control-drag from ClickerController to Clicker. The rules say to drag in the direction of the message. Dropping the drag onto Clicker makes the inspector bring up the Connections pane and I know enough to select "content" as the thing to bind to. I click Connect and it is done. Now the Cocoa-ey goodness that is bestowed on the NSOBjectController will be available to my Clicker class. But I don't know what that is yet. I'm just following how it is done.
There seem to be a number of ways for Cocoa applications to find things in the nib files in order to communicate with them. I'm confused about outlets, actions, and bindings, but since I'm trying to learn bindings (they look like less work), I will hook things up that way.
I set up the text field by selecting it and looking at its bindings in the inspector. I know that the binding I need is "value" and it is straightforward to select that and specify that ClickerController is the controller, the controller key is "selection" (because that is the reference to the object I need to get inside of, an instance of Clicker) and the Model Key path is sliderValue. The slider is set up the same way and the Click button set up with "target" set to "selection" and "clicked".
What is missing is any code. And that is where my fun begins. IB can create class code and I use that to make a template for Clicker. The interface (.h) file is easy:
I'm limiting myself to simple values rather than have to deal with instantiating too many things and falling into object retention traps. I don't pretent to understand that fully yet. The instance variable sliderValue that I bound the slider and the text field to in IB is defined here. I also declare the clicked method that the button will fire off due to its being bound.
Also because for bindings to work everything has to be KVO compliant. There have to be access methods that get and set the slider value. Part of the rules is that the names have to be right, so setSliderValue (case included) is my only choice for a setter, and sliderValue is my only choice for a getter.
The implementation proved to be harder. It took me days (of fragments of time) to get it right. Here is my first attempt:
Dragging the slider left and right works fine. By enabling "Continuously send action while sliding" in the Attributes pane of the inspector in IB the updating is "live". Without that only when I release the slider does the text field change. And I can set the slider location by typing in a value to the text field and pressing tab or return. But clicking the button does nothing.
The code above shows the clicked method doubling the sliderValue every time the Click button is clicked. I set breakpoints with the debugger and can see the value being doubled on every click, but no update is taking place. So next I try this modification:
I'll force an update by using the methods that tell whatever makes bindings work that I really am changing the value of sliderValue. No dice. So I move the willChangeValueForKey method calls into the clicked method like this:
Still nothing. Objective-C programmers everywhere groan as they read this because of the colossal blunders I am making. After two days of forced hair removal and changing all the bindings and most everything else I can find, I am still nowhere. I go off on a wild tangent trying to do things like this:
without understanding that there is no dependent key here: both the slider and the text field reference the same instance variable. Dependent keys are for when you have several values, any of which should cause another key to be updated. An example would be the x and y size of a rectangle. Either changing should cause a redraw.
So a posting to the Apple Cocoa mailing list is in order and gets me an answer. This is the correct code:
I didn't send the willChangeValueForKey to any object! I am not sure what the compiler thought of it, but it doesn't give me any warnings. And it works!
But another posting tells me that that is wrong. Since I am using bindings I should not have to use willChangeValueForKey at all: bindings do all that for you. What I had missed is this: if you update the sliderValue directly, then no accessor methods are called. For bindings to do their work behind the scene it is necessary to call the accessors. And to do that, send the accessor message to self.
So here is the final version that does work and works the correct way: 
But I am still puzzled about the NSObjectController object. Why is it there? It just seems to redirect the messages to Clicked class. So I redo the bindings so that they reference Clicker instead of ClickerController. And it still works. So what good is the object controller?
Another email to the list reveals two things: 1) the object controller handles placeholders. These are the pieces of text that appear that say No Selection and Multiple Selection. If you buy into the object controller you get that for free. But in my case I only have one object and it is always selected, so placeholders are not useful. 2) the object controller handles partial completion. This is for the case of when you have modified a field and press a button on the window. Do you want to keep or discard the change? Again, done automatically for you. But no use in my app's case.
Here is Clicker, finally working:

You can download the complete project from the downloads page.