Basics of Notifications

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

There is an instance of NSNotificationCenter available to every running 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:@selectordownloadDataComplete: 
                                   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;

Lets 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 
*--------------------------------------------------------------------------*/
- voiddownloadDataComplete: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:@selectordownloadDataComplete: 
                         name:NOTIF_DataComplete object:nil; 
 

 
#pragma mark -
#pragma mark Cleanup
 
/*---------------------------------------------------------------------------
* Cleanup 
*--------------------------------------------------------------------------*/ 
- voiddealloc 

  NSNotificationCenter defaultCenter removeObserver:self;
  super dealloc;

 
@end

Class That Posts Notification

To keep things simple, Ill 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
- voidapplicationDidFinishLaunching: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, Im 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 its 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.

Please follow and like us:

Leave a Reply

Your email address will not be published. Required fields are marked *