iOS 提供了一种 “同步的” 消息通知机制NSNotificationCenter,观察者只要向消息中心注册, 即可接受其他对象发送来的消息,消息发送者和消息接受者两者可以互相一无所知,完全解耦。
基于这点,我们可以用来两个对象之间的通信!
注意,每个运行中的application都有一个NSNotificationCenter的单例,如源代码:
+ (NSNotificationCenter *)defaultCenter;
只要任何一个对象注册消息通知,如果该消息被发送,那么该对象将能够收到消息通知;从而实现在这个对象去执行另外一个对象的函数;
使用方法:
1. 观察者注册消息通知
- (void)addObserver:(id)notificationObserver
selector:(SEL)notificationSelector
name:(NSString *)notificationName
object:(id)notificationSender
addObserver(观察者) : self
selector(收到消息后要执行的函数): notificationSelector
name (消息通知的名字): notificationName
object (消息发送者) : 表示接收哪个发送者的通知,如果第四个参数为nil,接收所有发送者的通知
使用实例:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:TEST_NOTIFICATION object:nil];
注意的问题:
(1)Observer不能为nil;
(2 )如果name设置为nil,则表示接收所有消息;
(3)监听同一条通知的多个观察者,在通知到达时,它们执行回调的顺序是不确定的,所以我们不能去假设操作的执行会按照添加观察者的顺序来执行
2. 发送消息通知(与观察者注册消息通知对应)
- postNotification:
– postNotificationName:object:
– postNotificationName:object:userInfo:
我们可以根据需要指定通知的发送者(object)并附带一些与通知相关的信息(userInfo),当然这些发送者和userInfo(注意,这里userInfo是个字典)可以封装在一个NSNotification对象中,由- postNotification:来发送。注意,- postNotification:的参数不能为空,否则会引发一个异常
使用实例:
[[NSNotificationCenter defaultCenter] postNotificationName:TEST_NOTIFICATION object:nil];
这样,就能够实现在两个类(或者一个类内回调)之间的消息通信,可以理解成实现了回调函数;
3.移除观察者(与观察者注册消息通知相对应)
- (void)removeObserver:(id)notificationObserver
- (void)removeObserver:(id)notificationObserver name:(NSString *)notificationName object:(id)notificationSender
引用博文NSNotificationCenter内容:
(1)由于注册观察者时(不管是哪个方法),通知中心会维护一个观察者的弱引用,所以在释放对象时,要确保移除对象所有监听的通知。否则,可能会导致程序崩溃或一些莫名其妙的问题。
(2)对于第二个方法,如果notificationName为nil,则会移除所有匹配notificationObserver和notificationSender的通知,同理notificationSender也是一样的。而如果notificationName和notificationSender都为nil,则其效果就与第一个方法是一样的了。大家可以试一下。
(3)最有趣的应该是这两个方法的使用时机。–removeObserver:适合于在类的dealloc方法中调用,这样可以确保将对象从通知中心中清除;而在viewWillDisappear:这样的方法中,则适合于使用-removeObserver:name:object:方法,以避免不知情的情况下移除了不应该移除的通知观察者。例如,假设我们的ViewController继承自一个类库的某个ViewController类(假设为SKViewController吧),可能SKViewController自身也监听了某些通知以执行特定的操作,但我们使用时并不知道。如果直接在viewWillDisappear:中调用–removeObserver:,则也会把父类监听的通知也给移除。
(4)关于注册监听者,还有一个需要注意的问题是,每次调用addObserver时,都会在通知中心重新注册一次,即使是同一对象监听同一个消息,而不是去覆盖原来的监听。这样,当通知中心转发某一消息时,如果同一对象多次注册了这个通知的观察者,则会收到多个通知。
4.关于同步异步
默认的NSNotificationCenter是同步的,这是一般人忽略的地方,可以参考这篇好文 NSNotificationCenter的同步和异步
本文参考了以下博文:
NSNotificationCenter
IOS 消息机制(NSNotificationCenter)