You want to broadcast an event in your app and allow any object that is willing to listen to it to take action, depending on the notification that you are broadcasting.
Use the postNotificationName:object:userInfo:
method
of the default notification center of type NSNotificationCenter
to post a notification
that carries an object (usually the object that fires the
notification) and a user-info dictionary that can carry extra
information about the notification and/or the object that fires the
notification.
Notification centers are dispatch
centrals for notification objects. For
instance, when the keyboard pops
up anywhere while the user is inside your app, iOS will send a
notification to your app. Any object inside your app willing to listen
to this notification can add itself to the default notification center
as an observer for that particular
notification. Once your object’s lifetime comes to an end, it must
remove itself from the notification center’s dispatch table. As a
result, a notification is a message that gets broadcasted to observers
through a notification center. A notification center is an instance of
NSNotificationCenter
class. We
retrieve the default notification center object using the defaultCenter
class method of NSNotificationCenter
.
Notifications are objects of type NSNotification
. A notification object has a
name (specified as NSString
) and
can carry two key pieces of information:
Note
You can specify the name of your notifications yourself. You don’t have to use an API for that. Just make sure that your notification names are unique enough that they won’t clash with a system notification.
- Sender Object
This is the instance of the object that fires the notification. The observer can access this object using the
object
instance method of theNSNotification
class.- User-Info Dictionary
This is an optional dictionary that the sender object can create and send alongside a notification object. This dictionary usually contains more information about the notification. For instance, when a keyboard is about to get displayed in iOS for any component inside your app, iOS sends the
UIKeyboardWillShowNotification
notification to the default notification center. The user-info dictionary of this notification contains values such as the rectangle of the keyboard before and after animation and the animation duration of the keyboard. Using this data, an observer can make a decision as to, for instance, what to do with UI components that potentially will be obstructed once the keyboard gets displayed on the screen.
Warning
Notifications are a great way of implementing decoupled code. By that I mean, using notifications,
you can get rid of completion handlers and delegation. However,
there is one potential caveat about notifications: they are not
delivered immediately. They are dispatched by notification centers,
and the implementation of NSNotificationCenter
is hidden from
application programmers. Delivery might sometimes be delayed by a
few milliseconds or in extreme cases (which I have never
encountered) a few seconds. As a result, it is up to you to decide
where to and where not to use notifications.
In order to construct a notification of type NSNotification
, use the notificationWithName:object:userInfo:
class
method of the NSNotificationClass
,
as we will soon see.
Note
It is best to suffix your notification names with the word
Notification
. For instance, it is
permitted to give your notification a name similar to ResultOfAppendingTwoStrings
. However, it
is better to give the name ResultOfAppendingTwoStringsNotification
,
as that clearly says what this name belongs to.
Let’s have a look at an example. We’ll simply take a first name and a last name, append them to create one string (first name + last name) and then broadcast the result using the default notification center. We will do that in the implementation of our app delegate as soon as the user launches our app:
#import "AppDelegate.h" @implementation AppDelegate @synthesize window = _window; /* The notification name */ const NSString *ResultOfAppendingTwoStringsNotification = @"ResultOfAppendingTwoStringsNotification"; /* Keys inside the dictionary that our notification sends */ const NSString *ResultOfAppendingTwoStringsFirstStringInfoKey = @"firstString"; const NSString *ResultOfAppendingTwoStringsSecondStringInfoKey = @"secondString"; const NSString *ResultOfAppendingTwoStringsResultStringInfoKey = @"resultString"; - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ NSString *firstName = @"Anthony"; NSString *lastName = @"Robbins"; NSString *fullName = [firstName stringByAppendingString:lastName]; NSArray *objects = [[NSArray alloc] initWithObjects: firstName, lastName, fullName, nil]; NSArray *keys = [[NSArray alloc] initWithObjects: ResultOfAppendingTwoStringsFirstStringInfoKey, ResultOfAppendingTwoStringsSecondStringInfoKey, ResultOfAppendingTwoStringsResultStringInfoKey, nil]; NSDictionary *userInfo = [[NSDictionary alloc] initWithObjects:objects forKeys:keys]; NSNotification *notificationObject = [NSNotification notificationWithName:(NSString *)ResultOfAppendingTwoStringsNotification object:self userInfo:userInfo]; [[NSNotificationCenter defaultCenter] postNotification:notificationObject]; self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; }
Of course, you don’t have to specify an object or a user-info
dictionary for every notification that you wish to broadcast. However,
if you are working with a team of developers on the same app or if you
are writing a static library, I suggest that you fully document your
notifications and clearly mention whether your notifications carry an
object and/or an user-info dictionary with them. If they do, you must
say what object each notification carries and what keys and values are
inside the user-info dictionary. If you are planning on not sending an
object or a user-info dictionary, then I suggest you use the
postNotificationName:object:
instance method
of NSBundle
. Specify a string that
represents the name of your notification as the first parameter, and
nil as the second parameter, which is the object that should be
carried with the notification. Here is an example:
#import "AppDelegate.h" @implementation AppDelegate @synthesize window = _window; /* The notification name */ const NSString *NetworkConnectivityWasFoundNotification = @"NetworkConnectivityWasFoundNotification"; - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ [[NSNotificationCenter defaultCenter] postNotificationName:(NSString *)NetworkConnectivityWasFoundNotification object:nil]; self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; }
Get iOS 5 Programming Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.