Thursday, July 24, 2008

Cocoa Bindings - Elementary

In this post I want to explore bindings in the very simplest way. I made a page a few years ago with more on it, but here we're starting small. (I should note that those examples are broken now because of the objc.ivar stuff, so I'll have to revisit them).

In XCode, make a new project called PyX as a standard Cocoa-Python Application, and in IB, I add to the window a button (labeled "go") and an NSTextField. In the PyXAppDelegate file put this code:

from Foundation import *
from AppKit import *

class PyXAppDelegate(NSObject):
s = objc.ivar("s")
x = 64

def applicationDidFinishLaunching_(self, sender):
NSLog("Application did finish launching.")
self.s = 'my text'

def go_(self,sender):
NSLog("go: %s" % sender.description())
self.x += 1
self.s = "%s %i" % (chr(self.x), self.x)

Go back to IB and hook up the button to the AppDelegate (it's sitting on the MainMenu.xib window). In addition, select the text field, and bring up the Bindings Inspector from the Tools menu. Bind the text field to the AppDelegate with the model key path as shown in the left-hand screenshot (it can be "s" or "self.s"). When I run the app, the window looks like the middle, and after I push the button once, it looks like what's on the right. Every time the button is pushed, we change the value of the variable self.s, and because the NSTextField is bound to that variable, it gets updated automatically. That's the absolute simplest demo of bindings that I can think of.

To have editing in the text field be reflected in our model object, we need to do two more things. First, in IB with the text field selected, bring up the Bindings Inspector and check the box marked "Continuously Updates Value." Then, add an accessory method to set the variable named s:

    def setS_(self,value):
NSLog("setS %s" % value.description())
self.s = value

That's it!