Basics of Notifications with NSNotificationCenter

March 25, 2009

What follows is a brief guide to working with Notifications in Cocoa. I’ll cover the basics, including registering an observer and posting notifications, just enough to start using notifications in your iPhone apps.

There is an instance of NSNotificationCenter available to every running iPhone application. This class acts as an intermediary to facilitate communication between objects that are interested in being notified at some point in the future (these objects are known as the observers) and a poster that posts to the notification center, resulting in all observers (registered for a specific notification) being called.

To give you an idea of where you might use notifications, consider how you might handle downloading of data in a background thread. I recently used notifications in this scenario as I wanted to be notified when a web-service call completed. Upon receiving a notification, I then proceeded to populate a view with the data retrieved, or with an error message if the data access failed.

The 30,000 foot view consists of two steps:

Step #1
Register an observer, which requests that a selector to be called when a specific notification is posted.

Step #2
Post a notification, which will result in all registered observers being called.

For example:

1
2
3
4
// Register observer to be notified when download of data is complete
[[NSNotificationCenter defaultCenter] addObserver:self 
                                   selector:@selector(downloadDataComplete:) 
                                   name:NOTIF_DataComplete object:nil];

This code registers an observer for a notification with the name NOTIF_DataComplete (more on that below). When a notification is posted with the same name, the method downloadDataComplete will be called.

Posting a notification with the name NOTIF_DataComplete would look as follows:

1
2
3
// Post notification that the download is complete  
[[NSNotificationCenter defaultCenter] 
                    postNotificationName:NOTIF_DataComplete object:nil];

Let’s show how this might like in a working example.

Class Registering as Observer

1
2
3
4
5
6
7
8
9
10
11
12
13
//  SomeClass.h
 
#import <Foundation/Foundation.h>
 
@interface SomeClass : NSObject 
{
 
}
 
// For name of notification
extern NSString * const NOTIF_DataComplete;
 
@end

Below is the code for the implementation of SomeClass. Notice on line 6 the name of the notification is defined. On line 40 we register as an observer for the named notification, specifying the selector @selector(downloadDataComplete:). Once the notification is posted, the method on line 26 is called.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//  SomeClass.m
 
#import "SomeClass.h"
 
// Name of notification
NSString * const NOTIF_DataComplete = @"DataComplete";
 
#pragma mark -
#pragma mark Private Interface
 
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Private interface definitions
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
@interface SomeClass (private)
- (void) dataDownloadComplete:(NSNotification *)notif;
@end
 
@implementation SomeClass
 
#pragma mark -
#pragma mark Private Methods
 
/*---------------------------------------------------------------------------
* Notifications of data downloads 
*--------------------------------------------------------------------------*/
- (void)downloadDataComplete:(NSNotification *)notif 
{
  NSLog(@"Received Notification - Data has been downloaded");
}
 
#pragma mark -
#pragma mark Initialization
 
/*---------------------------------------------------------------------------
* Initialization
*--------------------------------------------------------------------------*/
- (void) init
{
  // Other initialization code here...
 
  // Register observer to be called when download of data is complete
  [[NSNotificationCenter defaultCenter] addObserver:self 
                         selector:@selector(downloadDataComplete:) 
                         name:NOTIF_DataComplete object:nil]; 
 
}
 
#pragma mark -
#pragma mark Cleanup
 
/*---------------------------------------------------------------------------
* Cleanup 
*--------------------------------------------------------------------------*/ 
- (void)dealloc 
{
  [[NSNotificationCenter defaultCenter] removeObserver:self];
  [super dealloc];
}
 
@end

Class That Posts Notification

To keep things simple, I’ll add a few lines to the applicationDidFinishLaunching method to show you how posting a notification might look:

1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)applicationDidFinishLaunching:(UIApplication *)application 
{
  [window makeKeyAndVisible];
 
  SomeClass *someclass = [[SomeClass alloc] init];
 
  // ...
 
  // Post a notification that the data has been downloaded  
  [[NSNotificationCenter defaultCenter] 
            postNotificationName:NOTIF_DataComplete object:nil];
 
}

I create an instance of SomeClass and follow this by posting of a notification of the name NOTIF_DataComplete. This example is a little contrived, however, I’m sure you get the idea. Although a short example, it shows just how easy it is to register an observer and post notifications.

There are various other nuances to working with notifications that can be quite helpful when the time comes that you need more robust support for communication among objects. For example, you could specify that you are interested in receiving a notification by name (as above), however, only if that notification has a specific object affiliated with it. This would allow you to use the same notification name, however, only notify certain objects. One use of this could be if you have multiple downloads and want to use notifications to be notify a specific object that it’s download is complete.

If you are working with multiple threads, which would be the case if you need to fire off multiple downloads in the background, you can look into distributed notifications, which allow notifications to be delivered to a particular thread. For more information, you can read Introduction to Notification Programming Topics available in the iPhone Reference Library.

Download: Xcode project

9 comments

I have just been working with notifications, and have found two specific issues anyone working with them needs to know:

1. The notification center object does NOT retain the reference to the observer object.

2. If you add the same observer twice, it will be notified twice — the notification center does NOT cull duplicates. So make sure you either release before re-adding or only add once.

by Michelle on Mar 26, 2009. Reply #

Is it possible to get a list of possible notifications that are available?

by cloverfield on Mar 28, 2009. Reply #

I don’t know about a list, but if you did a desktop search in one of the folders that includes .h files, you would find all of the files that define them.

by Michelle on Mar 29, 2009. Reply #

Cheers, very well explained!!!

by David van Dugteren on Jul 2, 2010. Reply #

Thanks ,usually i fear about NSnotificationcenter but from today wow…thanks once again

by vasu on Dec 23, 2010. Reply #

Nice Articles, really helpful.

Keep posting.

by Kamleshwar on May 13, 2011. Reply #

Thanx…
I got it meaning of nodification…

by Mukesh on Jun 19, 2011. Reply #

thanks nice artical

by sandeep on Jul 1, 2011. Reply #

very well explained…easy to understand !

by raj singh on Sep 12, 2011. Reply #

Leave a Comment