2.7 Notifications

Notifications provide a mechanism for distributing information about events within an application. Notifications provide an alternative to messaging as a means for communicating between objects. Messaging requires that the sender of the message know who the receiver is when the message is dispatched. Effectively, the notifications system decouples the message sender from the message receiver. With notifications, a broadcast paradigm is implemented in which objects post notifications to a notification center, which then sends messages to objects (known as observers) which have registered their interest in the type of event, or the originating object.

The notification center is an instance of the NSNotificationCenter class; notifications are instances of the NSNotification class. Every notification object has a name identifying the notification type, an object associated with the notification that provides context for the notification, and an optional userInfo dictionary with which posters may pass additional information. When an observer registers with the notification center, it specifies a method to be invoked in response to the posting of a notification. Upon receiving a notification, the notification center identifies the observers of the specific named notification and invokes a predetermined method in each observer.

To obtain an instance of NSNotificationCenter, use the class method defaultCenter. This returns an application's default notification center. To register an object with the notification center, invoke the NSNotificationCenter method addObserver:selector:name:object:. The first argument in this method is the object that is added as an observer; this object is usually self. The selector: argument provides a method selector for the method that needs to be invoked in response to the notification. The parameter name: is the name of the notification, while the final argument lets you specify the object whose notifications you want to be notified of.

Observers can be flexible when specifying the granularity of which notifications they would like to respond to in the addObserver:selector:name:object: method. For example, if nil is passed to object:, then the observer is notified of all notifications of the specified name, regardless of the originating object. Alternatively, nil can be passed for the notification name and an object can be specified, which causes the observer to be notified of all notifications posted by the indicated object.

Objects that have registered with the notification center are responsible for removing themselves when they no longer wish to receive notifications or when being destroyed. It is particularly important to remove an observer object in the object's dealloc method, since the notification center does not retain observers. If you do not remove objects before they are destroyed, the notification center will attempt to send messages to objects that no longer exist, resulting in a runtime error.

To remove an object from the notification center, use either removeObserver: or removeObserver:name:object:. The first removes the specified object as an observer of all notifications from all objects; this is the method you should use before an object is deallocated. The second method selectively removes the specified object from the notification center.

NSNotificationQueue is a class that lets you change a notification center's delivery behavior. Each thread has its own notification queue, which has two duties. The first is to coalesce notifications so multiple notifications of the same name posted within a short time of one another are posted to the notification center only once. Second, the notification queue allows for asynchronous posting; the standard behavior of NSNotificationCenter handles notifications synchronously.

Cocoa uses notifications extensively. Most objects post notifications of some sort that other objects can use to coordinate actions between objects. For example, Chapter 7 shows how NSFileHandle uses notifications to handle asynchronous communication with a socket. Because of the large number of predefined notifications, we frequently find ourselves registering objects as observers to these notifications.

    Part II: API Quick Reference