NSNotification
一、添加通知
1.使用selector添加
- (void)addObserver:(id)observer
selector:(SEL)aSelector
name:(nullable NSNotificationName)aName
object:(nullable id)anObject;
2.使用block添加
- (id <NSObject>)addObserverForName:(nullable NSNotificationName)name
object:(nullable id)obj queue:(nullable NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block;
使用block添加了多个相同的通知,接受通知时会并发的调用。
二、发送通知
1.使用NSNotificationCenter中方法
- (void)postNotification:(NSNotification *)notification;
- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject;
- (void)postNotificationName:(NSNotificationName)aName
object:(nullable id)anObject
userInfo:(nullable NSDictionary *)aUserInfo;
2.使用NSNotificationQueue
- (void)enqueueNotification:(NSNotification *)notification postingStyle:(NSPostingStyle)postingStyle;
- (void)enqueueNotification:(NSNotification *)notification
postingStyle:(NSPostingStyle)postingStyle
coalesceMask:(NSNotificationCoalescing)coalesceMask
forModes:(nullable NSArray<NSRunLoopMode> *)modes;
使用该方法发送的异步通知,可以使用下列方法取消:
- (void)dequeueNotificationsMatching:(NSNotification *)notification coalesceMask:(NSUInteger)coalesceMask;
三、实现原理
typedef struct NCTbl { // 通知存储的数据结构
Observation *wildcard; // 保存没传名字没传对象的通知,是个链表
MapTable nameless; // 保存未传入名字的通知
MapTable named; // 保存传入名字的通知,传入名字未传入对象的会创建一个相同的key
} NCTable;
typedef struct Obs {
id observer;
SEL selector;
struct Obs *next;
struct NCTbl *link;
} Observation;
四、发送通知到指定线程
- 判断接受通知不在指定线程,发送一个信号让指定线程处理。参考
- 通过子类化NSNotificationCenter或者单独写个类完成转发。
五、总结
- SEL方式添加的通知,接收通知和发送通知在同一线程。
- 对象销毁时记得移除观察者,通过SEL添加的iOS9以后可以不用移除;而通过block形式添加需要手动移除。
- 通过添加nil的通知,可以捕获到系统事件通知,包括线程销毁、亮度改变、锁屏、剪切板变动等。
- CFNotificationCenterGetDarwinNotifyCenter()可以跨进程进行通知,但是不能传递对象。
参考
-[1] 官方文档
-[2] Stackoverflow
网友评论