Tag Archives: NSNotificationCenter

NSNotificationCenter part 4: Asynchronous notifications with NSNotificationQueue

This article is the fourth part of a series about NSNotificationCenter. Head over part 1 for the basics of receiving and sending notifications.

Notifications are synchronous by default, meaning that the object that posts a notification must wait until the notification center dispatches the notification to all observers and each of them handles it before it can resume its execution. This might be inconvenient for objects that post frequent notifications (e.g., a UI component that notifies on every touch movement), and Foundation offers mechanisms to coalesce and delay notification via NSNotificationQueue.

NSNotificationQueue is a buffer of notifications that handles when to post them based on given criteria and the run loop, in a FIFO fashion. Each thread has a default notification queue via defaultQueue.

A word of warning

The NSNotificationQueue documentation appears to be in a state of flux after a OS X release note that basically discourages its use. From the release note:

NSNotificationQueue is an API and mechanism related to run loops (NSRunLoop), and the running of run loops. In particular, posting of notifications via the notification queue is driven by the running of its associated run loop. However, there is no definition for what run loop a notification queue uses, and there is no way for a client to configure that. In fact, any given notification queue might be “tickled” into posting by nearly any run loop and different ones at different times (and given that enqueued notifications are also mode-specific, what mode(s) the run loop(s) are running in any any given time also come into play). Further, although each notification queue is “thread-specific” (see the +defaultQueue documentation), there has never been any relationship between that thread and the run loop used by a notification queue. This is all more and more problematic as more and more things move to happening on different and new threads.

The practical upshot is:

  • Notifications posted through a queue might not be posted in any particular “timely” fashion;
  • Notifications posted through a queue might not ever be posted (the run loop of the thread that the queue chose to ask to poke it might not be run again; for example, the thread of that run loop might exit and the notification queue discarded);
  • Notifications can be posted by any given queue on a different thread than the thread the queue is the default queue for (when a queue is a default queue for some thread);
  • Notifications can be posted by any given queue on different threads over time;
  • There is no necessary/guaranteed relationship between the thread(s) on which notifications are enqueued and those on which the notifications eventually get posted (delivered) for any notification queue

This is true for all releases of OS X. Foundation and AppKit do not use NSNotificationQueue themselves, partly for these reasons.

Taking this into account, and until Apple clarifies their stance on this class, you shouldn’t assume that notifications posted with NSNotificationQueue will ever be posted, or received in any particular thread.

Delaying and Coalescing notifications

NSNotificationQueue‘s enqueueNotification:postingStyle: is used to post a notification asynchronously. Unlike NSNotificationCenter‘s postNotification: and its convenience methods, it immediately returns to the invoking object after putting the notification in the queue. The delay will depend of the given posting style. There are three options:

  • NSPostNow: The notification will be posted synchronously. If not used with coalescing, this would be exactly the same as postNotification:.
  • NSPostASAP: The notification will be posted when the current iteration of the run loop completes, much like a zero-delay timer (credit to Mike Ask for the analogy).
  • NSPostWhenIdle: The notification will be posted when the run loop is in a wait state or idle. This is handy for notifications that are not very important.

An example:

Delayed notifications are most useful when combined with coalescing, as the object creating the notifications might queue more before the first one is posted. By default, notifications queued with enqueueNotification:postingStyle: are coalesced by both the notification name and sender. The result is that when a notification is posted, it is the first notification queued for the corresponding name and sender; the rest have been coalesced (discarded, in effect).

By coalescing notifications we can make sure that a single notification is posted for repeatable events (e.g., receiving fresh data from a socket). This can be further controlled with NSNotificationQueue‘s enqueueNotification:postingStyle:coalesceMask:forModes:, which expands the delay options covered above with a coalescing criteria. The options are:

  • NSNotificationNoCoalescing: Do not coalesce notifications in the queue.
  • NSNotificationCoalescingOnName: Coalesce notifications with the same name.
  • NSNotificationCoalescingOnSender: Coalesce notifications with the same object.

The coalesce mask is a bit mask that allows us to combine NSNotificationCoalescingOnName and NSNotificationCoalescingOnSender to obtain the default behavior of enqueueNotification:postingStyle:.

Additionally, we can provide an array of run modes in which we want the notification to be posted. This typically will be nil, which is the equivalent to NSDefaultRunLoopMode. The following lines provide the same result:

Given that it is not possible to know exactly when the notification will be posted, the sender might be deallocated before its notifications are posted. A way around this is to dequeue the sender’s notifications before dealloc with dequeueNotificationsMatching:coalesceMask:.

Further reading

NSNotificationCenter part 3: Unit testing notifications with OCMock

This article is the third part of a series about NSNotificationCenter. Head over part 1 for the basics of receiving and sending notifications.

In order to avoid writing unit tests we are sometimes eager to declare our code as “untestable”. Like most code, notifications can be perfectly unit tested, and this is particularly straightforward with synchronous notifications, which are the most common kind.

Below we show how to test that synchronous notifications are posted (or not) and validate their userInfo with a little help from the superb Objective-C mocking framework OCMock. Finally, we share a few tips for unit testing observers.

For convenience, the code examples will not use STAssertNoThrow for exception failures.

Testing notification posting

OCMock provides an observer mock. This can be used to test that a particular method posts a particular notification, with the only requirement being knowing the name of the notification. A notification test requires a handful of lines of code:

First we register the observer mock for a specific notification and sender using a category extension provided by OCMock. Then, we tell the mock object to expect the notification from the sender. Since notifications are synchronous by default, right after we call the code that posts the notification we can simply verify the mock object. If the notification was received the observer mock will pass verification, otherwise it will fail.

Finally, like any other observer, once we’re no longer interested in the notification we remove it from `NSNotificationCenter.

Testing unwanted notifications

Some methods might post a notification only if certain conditions are met. A good test suite would also test that the notification is not sent if the conditions are not met. Luckily, the default behavior of the mock observer provided by OCMock is to raise an exception when an unexpected notification is received. The code to test this case is even simpler:

Validating userInfo

When the notification is expected to include specific userInfo keys we should also test that their values are correct. Again, OCMock comes to the rescue:

This is exactly the same than the first unit test example expect for a block that validates the userInfo property, passed using OCMock’s checkWithBlock: method.

Testing the observer

NSNoticationCenter calls observers by a given selector. For unit testing purposes, this selector is part of the public API of the observer class and as such should be included in the test suite.

To test the observer selector we will most likely need to provide it a notification parameter. While NSNotification is not meant to be initialized directly, we can use its static methods notificationWithName:object: and notificationWithName:object:userInfo: to create the notification. Alternatively, we can create a mock notification with OCMock.

Further reading

NSNotificationCenter part 2: Implementing the observer pattern with notifications

This article is the second part of a series about NSNotificationCenter. The previous part covers the basics of receiving and sending notifications.

If you ever tried implementing the observer pattern in Objective-C you might have noticed the need of using a non-retaining collection for the observers to avoid retain cycles, among other caveats.

Instead of writing your own custom observer implementation, a much leaner approach is using NSNotificationCenter. We could of course use it directly, but we would lose the strong typing expected from the observer pattern. Here’s how to implement this popular pattern with NSNotificationCenter at its core.

Typed observer

First, we define the observer protocol. In this example we will observe a custom audio player (HPEAudioPlayer):

Each observer method will correspond to a notification, hence the single notification parameter. The observer will not need to know the notification name; this will be an implementation detail.

Then, we add methods in our observable class to add and remove observers.

In the implementation of our observable class we define constants for the notification names:

Adding and removing the observer is reduced to calling NSNotificationCenter with the appropriate filters:

Finally, notifying the observers is as simple as posting the corresponding notification. NSNotificationCenter will take care of the rest.

Typed parameters with categories

When using the observer pattern one would expect the notification methods to have well-defined and typed parameters. Unfortunately, in the example above we’re using a generic NSNotification as our single parameter. What is the object? What is inside userInfo? We can do slightly better by using a category on NSNotification to explicitly answer these questions.

For our audio player example, we could have the following category:

By using these category methods the observer does not need to worry about casting the object property and doesn’t need to know the keys of the userInfo dictionary, or use it at all. Note that the additional properties are readonly, as NSNotification objects are expected to be immutable.

The category approach has still a problem, which is that the observer must know which category methods are available for each notification method (e.g., hpe_endTime is not defined for audioPlayerDidStartPlackback:). This can be solved by subclassing NSNotification.

Typed parameters with subclassing

Subclassing NSNotification allows us to provide a fully typed observer, including parameters, by giving each notification method its own notification subclass. Our observer protocol becomes:

As indicated in part 1, NSNotification is a class cluster that throws an exception if init is called. The implementation of its subclasses requires a few lines of boilerplate code:

Again, note that the properties are readonly to keep the notifications immutable.

The subclassing approach allows us to provide a fully typed observer at the expense of creating one class per method and dealing with NSNotification subclassing quirks. If strict typing is not required, the category approach is also valid as long as the parameters of each method are properly documented.

Further reading

NSNotificationCenter part 1: Receiving and sending notifications

Perhaps because it’s often paired with the much maligned KVO, or because the delegate pattern is so ubiquitous, NSNotificationCenter is frequently overlooked and misunderstood. Yet when it comes to broadcasting notifications to any object willing to listen, NSNotificationCenter has all your bases covered, and does so with a minimal number of methods and classes.

If you ever found yourself bubbling up events via delegates, pondering on how to avoid retain cycles when implementing the observer pattern, or working around blocks to deal with users leaving and then returning to a new UIViewController instance, chances are there was a much cleaner, decoupled solution using notifications.

This article is the first part of a series about NSNotificationCenter. Part 1 covers how to receive and send notifications while addressing common misconceptions. Part 2 provides a typed implementation of the observer pattern with notifications. Part 3 shows how to unit test notifications with a little help from OCMock. Part 4 deals with asynchronous notifications using NSNotificationQueue. Finally, a list of all public notifications in iOS and OS X are included as annexes.

While iOS classes will be used for examples, everything applies to OS X as well.

Notifications classes

Foundation provides 3 classes to deal with all your notification needs:

  • NSNotification: represents a notification.
  • NSNotificationCenter: broadcasts notifications and manages observers. Each app has a default notification center via defaultCenter.
  • NSNotificationQueue: coalesces and delays notifications. Each thread has a default notification queue via defaultQueue.

OS X offers a fourth class called NSDistributedNotificationCenter for communication between processes. We will not cover this class in this series.

Receiving notifications

To receive a notification you only need to know its name. Cocoa and Cocoa Touch are full of interesting and descriptively named notifications such as UIKeyboardWillShowNotification and UIApplicationDidReceiveMemoryWarningNotification. There are 165 public notifications in iOS 7.0 (annex A) and 393 in OS X 10.9 (annex B). Later we will see how to create your own notifications as well.

Receiving a notification takes very little code. Say you want to receive a memory warning (UIApplicationDidReceiveMemoryWarningNotification) outside a UIViewController, to clear a cache of some object. This is how it could look:

Adding the observer

The object that receives notifications is called observer, and must be added to a NSNotificationCenter. Unless you have a very strong reason not to, that will always be the defaultCenter.

init and viewDidLoad and viewWillAppear: in UIViewController are good candidates for adding observers. You should add the observer as late as possible and remove it as soon as possible to improve performance and avoid undesired side effects.

Observers register to a specific notification by specifying the name of the notification (usually a constant) and the sender of the notification as filters. Both are optional; in the above example, we don’t care who the sender is so we pass nil.

Specifying the sender is useful when different instances are sending notifications of the same name (e.g., you might be interested in the UITextFieldTextDidChangeNotification of a specific UITextField). If no sender is provided, you will receive all notifications with the given name. If no notification name is specified, you will receive all notifications of the given sender.

Handling the notification

Observers will receive notifications until they are removed from the NSNotificationCenter. Each notification is sent once per addObserver call. If you are receiving more notifications than expected, it might be a sign that you added the observer more than once (e.g., this might happen if you register the observer for notifications in viewWillAppear and unregister it in dealloc).

NSNotificationCenter will call the selector provided in addObserver:selector:name:object: with a single argument of type NSNotification. The selector is called in the same thread in which the notification was posted. Typically this is the main thread, so only check if the selector is running in a different thread if the corresponding documentation says otherwise.

The NSNotification object is a box of chocolates. It comes with an object id which is usually the sender of the notification and an userInfo dictionary with additional information about the notification. For example:

Knowing the contents of this dictionary for a specific notification might require debugging or -god forbid- reading the documentation. Don’t assume that any particular key will be present unless told otherwise.

You can also handle notifications with blocks to make unit test enthusiasts cringe. The initial example becomes:

The queue parameter is for asynchronous notificaions and is explained in part 4.

Removing the observer

The observer must be removed eventually, and you should do it as soon as you don’t need the notifications anymore. This is at best right after receiving the notification (e.g., to update the UI after MPMoviePlayerPlaybackDidFinishNotification) or at worst in dealloc. If you forget to remove the observer, NSNotificationCenter might send a notification to a deallocated instance, causing shenanigans.

NSNotificationCenter provides two methods to remove observer. removeObserver: and removeObserver:name:object:. The former unregisters the observer for all notifications, and the latter does so for notifications of the given name and sender, either of which can be nil. While it might be tempting to simply call removeObserver:, this is a bad practice as you might be unregistering from notifications registered elsewhere (e.g., in a superclass, subclass or category). Try to be as specific as possible when removing the observer.

As shown above, you also need to remove the observer when using blocks. In this case the observer is the object returned by addObserverForName:object:queue:usingBlock:. With these block observers you can use the single parameter removeObserver: more comfortably.

Sending synchronous notifications

Notifications are great to broadcast events that might be of general interest, such as model changes, user actions or the status of background processes. Unlike the delegate pattern, notifications can be used to notify various stakeholders and add very little coupling (in most cases, the observer only needs to know the notification name).

Naming notifications

The first step in creating your own notification is choosing a unique name. The document Coding Guidelines for Cocoa suggests:

For example:

  • Good: @"HPEAudioPlayerDidStartPlaybackNotification"
  • Bad: @"didStartPlayback"

The notification name should be a public constant. This will allow you to change the name of the notification without requiring any changes in the observers.

Posting the notification

Each app has a default NSNotificationCenter instance that can be used to broadcast notifications. You can create the notification object yourself and post it, or use a couple of convenience methods that do this. If you don’t need to send any additional information, posting a notification is as simple as:

The object parameter is typically used to pass the object sending the notification, normally self. NSNotificationCenter will create a NSNotification object for the given name and the given sender, and no additional information.

The notification is then sent to every registered observer in no defined order. Notifications are posted synchronously, meaning that postNotification: and its convenience methods will not return until all observers have processed the notification. Additionally, observers will be called in the same thread in which the notification is posted. Unless you explicitly state otherwise, observers will expect this to be the main thread.

Consider a background operation that notifies progress periodically. We want to send the notification and continue with our operation as soon as possible, and notify the observers in the main thread. A way to do this is with dispatch queues:

Sending additional information

In most cases you will want to send additional information with the notification, such as the progress value in the example above. Notifications can have a dictionary with custom data called userInfo. NSNotifcationCenter offers a convenience method to post notifications with userInfo:

Again, you should define any userInfo keys as public constants.

Subclassing NSNotification

If the userInfo dictionary does not suit your needs or if you prefer typed atributes you can also subclass NSNotification, with a few caveats. NSNotification is a Cocoa class cluster, which is another way of calling an abstract class. In particular, it does not implement name, object and userInfo and throws an exception if you call init.

Because of these caveats, subclassing NSNotification is generally frowned upon and some developers prefer to use categories. Full examples of both approaches are provided in part 2 where we implement a typed observer with notifications.

When using your own NSNotification subclass, the convenience methods to post the notification are no good. You are responsible for creating the notification object, and provide the name, object and userInfo (if applicable) either in the subclass implementation or before calling postNotification:. For example:

Further reading