First Steps with Cocoa Bindings
Most programmers are familiar with the
model-view-controller pattern, or MVC for short. Model objects provide the core
program logic; view objects provide a visual representation of the data and
controls for the user to manipulate; and controller objects comprise the mess
between, coordinating the model with the view. The controller layer updates the
view when the model changes, and updates the model in response to the user's
input. With the addition of Cocoa bindings in OS X 10.3, Apple has provided
developers with a technology that can minimize --- and in simple cases even
eliminate --- writing controller code...

I'd
read some of Apple's
documentation on Cocoa Bindings as well as a great article by Michael
Beam titled The
Cocoa Controller Layer. I worked
through a preferences example, but I still didn't really have a feel for this; I
needed to go exploring on my own. I had a small app coded up using Cocoa's
target/action scheme, and thought I'd see what it'd look like coded with
bindings instead.In this very simple
app, the controller and model code were munged together in the same class. I'm
no purist, at least not for little one-off apps that no one but me will ever
see. The basic approach with Cocoa's target/action isn't fundamentally different
than what we'd see in MFC or even .NET WinForms: you end up with some class
members that hold references to controls in the view, such as buttons and text
fields, allowing the controller code to gray out the buttons or initialize the
text fields. You also have controller code to handle events from the view, such
as button clicks or a key presses. Setting this stuff up is very different
between Cocoa and MFC and .NET, but strip it down to the basics and that's what
you have.For my small app, I was able
to dispose of my controller code almost entirely using Cocoa
bindings.I created an instance of
NSObjectController
in Interface Builder and associated it with my model object. Since my model
object was also instantiated in Interface Builder, all I needed to do to
associate the controller with the model was to Ctrl-drag between their icons,
and click a button to set the controller object's
content
member to my model object. After that I used the
Bindings
tab in Interface Builder's inspector to bind each control to data members in my
model object.The code that was left
didn't have
NSTextField
pointers to the text fields, nor a
NSProgressIndicator
pointer for that control. A little code remained to animate an on-the-fly change
in the window size, but beyond that it was just my model and its data. At
runtime, changes to the data result in changes to the controls, and vice-versa;
all with no visible code
whatsoever.Besides the obvious benefit
of not having to write and debug the controller code, this also left me with a
class far easier to unit test. Of course, had I designed properly in the first
place, the controller layer would've been off in its own class, but in practice
I've seldom seen GUI controller code separated this well from model code. I'm
used to tools that let me draw a dialog and create a class pre-populated with
members to access its controls, and too often I've yielded to the temptation to
do too much work in that class. The
downside of bindings is that it's difficult to troubleshoot what you can't
trace. My first attempt didn't work because I forgot to set the controller
object's
content
member to my model object, and it took some poking around to figure out what I
did wrong. Another problem is that bindings are fairly new to OS X; if you use
them, you're limited to OS X 10.3 and
up.It still makes sense to have the
target/action pattern available for some tasks, such as reacting to button
clicks. But for moving data between the model and view, Cocoa bindings look
pretty slick.
Posted: Thu - March 24, 2005 at 05:24 PM