Patterns in Objective-C: Observer Pattern
Posted 12/14/2008 - 18:16 by David
One of the most common patterns, after the Singleton, in Java is the Observer Pattern. Also referred to as a Broadcaster/Listener or a Publish/Subscribe pattern. The basic principle is that there are two components: An Observer (or Listener) and a Subject (or Broadcaster).
The basic idea is that a listener registers with a broadcaster using some predefined protocol. At some later point, the broadcaster is told to notify all of its listeners, where it calls some function on each of its listeners and passes certain arguments along. This allows for asynchronous message passing between two different objects that don't have to know about one-another, they just have to know about the broadcaster.
Examples of where this gets used are to track database updates (i.e., listeners want to know when the database updates in specific ways), handle click events, or implement shutdown hooks.
Apple has provided an Observer Pattern in the Cocoa library called the NSNotificationCenter
. There are three primary tasks that are performed with the NSNotificationCenter
:
-
Adding a Observer
-
-
[ [ NSNotificationCenter defaultCenter ] addObserver :listener selector : @selector (notify : ) name : @ "Event" object :notificationSendert ];
Here we see several components:
[NSNotificationCenter defaultCenter]
- While one can create their ownNSNotificationCenter
s, for most purposes it is sufficient to use the default.addObserver:listener
-listener
is the object that will be notified by theNSNotificationCenter
. For many applications the observer will "self register" with the observer, and thus the call will beaddObserver:self
.selector:@selector(notify:)
- Indicates which method should be called when the observer is notified.name:@"Event"
- The name of the event that will cause theNSNotificationCenter
to notify the observer. It is a good practice to use an extern string constant instead of directly inserting the string.object:notificationSender
- ThenotificationSender
represents the object that will post the notification. This is frequently used when the object in question needs to berelease
d once a notification happens.
This is frequently
nil
, meaning that theNSNotificationCenter
will not consider the sender when deciding whether to fire the event. If it is notnil
, then only notifications sent from that specific object will fire the event (see below).Note that if
name
is left asnil
then all notifications sent by thenotificationSender
will fire the event.The notify function can be any function that takes a single argument:
-
id notificationSender = [notification object ];
-
//do stuff
-
}
Notifying the Observers
-
-
In some cases, such as when registering for events with Cocoa's built-in libraries (e.g.,
MPMoviePlayerController
) the notification event is called by the library when a certain condition is met, for example when the movie ends.In other cases, we will want to trigger that event:
-
[ [ NSNotificationCenter defaultCenter ] postNotificationName : @ "Event" object :notificationSender ];
The components here are similar to when we added the observer above. The
postNotificationName
is identical to thename
, and theobject
is thenotificationSender
.
Removing an Observer
-
-
When we are done with the observer, we will want to unregister it with the
NSNotificationCenter
:-
[ [ NSNotificationCenter defaultCenter ] removeObserver :listener name : @ "Event" object :notificationSender ];
The arguments here are the same as when we added the observer.
-