iOS开发

iOS通知使用总结

2020-06-25  本文已影响0人  SayCain

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;

四、发送通知到指定线程

  1. 判断接受通知不在指定线程,发送一个信号让指定线程处理。参考
  2. 通过子类化NSNotificationCenter或者单独写个类完成转发。

五、总结

  1. SEL方式添加的通知,接收通知和发送通知在同一线程。
  2. 对象销毁时记得移除观察者,通过SEL添加的iOS9以后可以不用移除;而通过block形式添加需要手动移除。
  3. 通过添加nil的通知,可以捕获到系统事件通知,包括线程销毁、亮度改变、锁屏、剪切板变动等。
  4. CFNotificationCenterGetDarwinNotifyCenter()可以跨进程进行通知,但是不能传递对象。

参考

-[1] 官方文档

-[2] Stackoverflow

上一篇下一篇

猜你喜欢

热点阅读