NSNotification in iOS: A Mechanism for Decoupled Communication
Core Components of a Notification
A notification encapsulates data exchanged between objects. It consists of three primary elements:
name: An identifier for the notification type.object: A reference to the entity that posted the notification.userInfo: A dictionary containing supplementary data passed from poster to receiver.
@property (readonly, copy) NSString *name;
@property (nullable, readonly, retain) id object;
@property (nullable, readonly, copy) NSDictionary *userInfo;
Creating Notification Instances
Notifications can be instantiated using factory methods or designated initializers.
// Class factory methods
+ (instancetype)notificationWithName:(NSString *)notificationName object:(nullable id)sender;
+ (instancetype)notificationWithName:(NSString *)notificationName object:(nullable id)sender userInfo:(nullable NSDictionary *)additionalData;
// Initializer
- (instancetype)initWithName:(NSString *)notificationName object:(nullable id)sender userInfo:(nullable NSDictionary *)additionalData;
Posting Notifications to the Center
An object can dispatch notifications via the default notification center.
// Post a pre-configured notification instance
- (void)postNotification:(NSNotification *)notification;
// Post by specifying name and sender
- (void)postNotificationName:(NSString *)notificationName object:(nullable id)sender;
// Post with name, sender, and additional data
- (void)postNotificationName:(NSString *)notificationName object:(nullable id)sender userInfo:(nullable NSDictionary *)additionalData;
Registering Observers
Objects interested in specific notifications must register with the notification center.
Selector-Based Registration
The observer provides a method to be called when the notification arrives.
- (void)addObserver:(id)receiver
selector:(SEL)handlerMethod
name:(nullable NSString *)notificationName
object:(nullable id)sender;
Block-Based Registration
A block is executed upon notification receipt.
- (id)addObserverForName:(nullable NSString *)notificationName
object:(nullable id)sender
queue:(nullable NSOperationQueue *)targetQueue
usingBlock:(void (^)(NSNotification *note))eventHandler;
The targetQueue specifies where the block runs; nil implies the current queue.
Unregistering Observers
Observers must deregister before being deallocated to prevent crashes.
// Remove all registrations for an observer
- (void)removeObserver:(id)receiver;
// Remove specific registrations for an observer
- (void)removeObserver:(id)receiver
name:(nullable NSString *)notificationName
object:(nullable id)sender;
Example deallocation code:
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
System-Generated Notifications
UIDevice Events
The singleton UIDevice instance broadcasts state changes.
UIDevice *device = [UIDevice currentDevice];
Relevant notifications include:
UIDeviceOrientationDidChangeNotificationUIDeviceBatteryStateDidChangeNotificationUIDeviceBatteryLevelDidChangeNotificationUIDeviceProximityStateDidChangeNotification
Keyboard Activity
The system posts notfiications related to keyboard appearence and geometry.
UIKeyboardWillShowNotificationUIKeyboardDidShowNotificationUIKeyboardWillHideNotificationUIKeyboardDidHideNotificationUIKeyboardWillChangeFrameNotificationUIKeyboardDidChangeFrameNotification
Accompanying userInfo dictionary keys:
UIKeyboardFrameBeginUserInfoKeyUIKeyboardFrameEndUserInfoKeyUIKeyboardAnimationDurationUserInfoKeyUIKeyboardAnimationCurveUserInfoKey
Comparison with Delegation
Both delegation and notifications facilitate communication between objects. However, delegation establishes a one-too-one relationship, where as notifications support a many-to-many pattern.