Target+action from a Javascript standpoint

In Javascript, you sometimes need to supply a function to be used as notification. Whether it be onload, onclick, xmlHttpRequest.onreadyStateChange or setTimeout, setInterval, you'll have to supply a function to know what's happening. And here lies the catch : it's just a function. If you want to use one of your objects' method, you'll have to wrap it in a closure :
// Our custom object
function MyObject() {}
MyObject.prototype = {
  notifyWhenXmlHttpRequestChanged : function (x)
     // do stuff when receiving notification

// instance of our custom object
var myObject = new MyObject

// Use an instance method as notification
xmlHttpRequest.onreadystatechange = function (x) { myObject.notifyWhenXmlHttpRequestChanged(x) }

That's because Javascript loves functions : they are first class, meaning they get treated the same as objects, numbers and strings — you can create, modify, delete them anytime. In Objective C, objects reign supreme and functions don't get any love. Therefore ObjC always notifies a method (action) of an object instance (target). Our onreadystatechange notification would look like that :

[xmlHttpRequest setTarget:myObject];
[xmlHttpRequest setAction:@selector(notifyWhenXmlHttpRequestChanged:)];

@selector is the ObjC way of specifying a method name. It's still just a string.

That's it. Supply an instance and a method name, and ObjC will know what to call. Target/Action is used in every NSControl and is the standard way to react to an UI event : when being clicked, an NSButton will call its target/action. This is how you're notified of a click, you can use any method of any object to act on it.

Interface Builder and one limit

In IB, target and action are setup both at the same time by right-dragging from an interface element (button, checkbox, …) to an object instance. (Your instances are listed in the window containing File's Owner, First Responder, …) You can therefore bind a button of you window to ApplicationController.clickedSomeButton:.

Unfortunately, you can't use keyPaths to set your target object, so you can't use ApplicationController.someObject.clickedSomeButton:. There's nothing preventing it (you can do it in code), but it's not available in IB.

Objective-C from Javascript

Follow me on Twitter
Planet Cocoa

2011 02 22Distance field
2010 07 202Binding through NSApp
2010 05 122Forwarding invocations
2010 02 272Core Image black fringes
2010 02 21Quickest Way to Shell
2010 02 08Who's calling ?
2009 09 2138 ways to use Blocks in Snow Leopard
2009 08 182Bracket Mess
2009 08 124Taming JavascriptCore within and without WebView
2009 04 15Debugging with Activity Monitor
2009 03 25How Core Image Color Tracking works
2009 03 1510Custom NSThemeFrame
2009 03 10Which framework is running ?
2009 03 074CoreUI can paint pretty big
2009 02 18Localization with functions
2009 01 30Did you forget to nest alloc and init?
2009 01 16JSCocoa on the iPhone
2009 01 11Mixing WebView and JavascriptCore
2009 01 09Badge overflow
2009 01 09Find your Garbage Collection leaks with Instruments

Powered by MediaWiki