Nov 2009

Passing Messages: Notifications, Delegates and Target-Action

Developing on the Mac or iPhone requires passing messages between objects. A button is touched or clicked, it sends a message to the controller to do something or the current playing song changes, a message saying this is sent out. Cocoa has three major conventions to pass messages, which this tutorial will cover and suggest the right times to implement these conventions.


Notifications
Notifications, specifically through the NSNotificationCenter, is a convention that allows objects to interact with the equivalent to a mail carrier. An object gives a message to the notifcation center, the mail carrier, and the notification center gives the message to any object that enlists to recieve that notification. Notifications are great for objects posting messages that might not even care if anyone is listening and don’t require anything back for that notification. A great example is Music Library API included in the iPhone OS 3.0. Notifications are sent by the music player when either the playback status, current playing track or volume changes. Notifications are a good choice here because any object might enlist in getting this information and the Music Player doesn’t expect anything back for sending out the notification.
Implementing a notification is pretty simple, to send a message implement this:

[[NSNotificationCenter defaultCenter] postNotificationName:@"MessageName" object:self];

And to recieve a message,

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(action:) name:@"MessageName" object:sender];

Delegates
Delegates are a common occurence in Cocoa. Delegates are unlike notifications because an object can have only one delegate to send messages to whereas a notication can be sent to a multitude of objects.  A delegate relationship is a relationship between two objects in which one object sends messages (in the form of functions) from one object to another. The object that sends the message gets to decide which messages to send, and the delegate object can be required to implement a response to these messages. For example, a table view delegate object is sent a message from the table view that a cell has been selected and a table view may require a delegate to provide information about the number of cells in a table.

Delegates are great to implement when an object needs certain information, but the object doesn’t want to require subclassing to obtain this information. Views are great candidates for implementing delegates because they require data to create their view. A table view acts a certain way, but the information – the cells – of the table change depending on the data set.

Target-Action
The Target-Action is similar to delegation in that messages are sent between two objects in a one way direction, but implementing a target-action is simpler than using delegates. With this convention, the object being sent the message tells the message sender which action – a selector  such as “@selector(doAction)” – to send. When a message is sent, the receivers action is automatically called. Recall in delegation, the message receiver must implement methods implemented by the sender, whereas here, the receiver tells which method to call. Buttons are prime examples when to implement target-action because buttons only need to send one message when it is clicked. Here is an example of how to send a message:

id target = ...;// defined elsewhere
SEL action = ...; // defined elsewhere
[target performSelector:action];

Because the target-action treats actions more like objects in a sense, the message sent should be limited one or two different messages. A good example of when you might want to send two different message is an network connect like

[fileDownloader downloadFile:(NSURL*)url target:(id)target didSucceed:(SEL)succeed didFail:(SEL)failed]


I hope this article helped you understand the different ways for objects to communicate in Cocoa. The best way to gain a further understanding is by practicing implementing these conventions yourself. If you’ve look at the few snippets of code I included, you’ll notice that the Notifications centers are simply places to manage target-actions. Delegates, the most complex convention to implement, require defining a protocol. The best way to learn how to implement delegation is to look at the header file of UITableView or NSTableView include in the Cocoa frameworks. Here you will find out how to define the delegate protocol, and how create the delegate property variable. Sending the message is a simple as calling [delegate delegateMethods:args].


Filed under Development

Copyright © 2010 Devin Ross