和delegate一样,KVO和NSNotification的作用也是类与类之间的通信,与delegate不同的是1)这两个都是负责发出通知,剩下的事情就不管了,所以没有返回值;2)delegate只是一对一,而这两个可以一对多。这两者也有各自的特点。
1)KVO的使用:
被观察者发出 addObserver:forKeyPath:options:context: 方法来添加观察者
- (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context Parameters anObserver The object to register for KVO notifications. The observer must implement the key-value observing method observeValueForKeyPath:ofObject:change:context:. keyPath The key path, relative to the receiver, of the property to observe. This value must not be nil. options A combination of the NSKeyValueObservingOptions values that specifies what is included in observation notifications. For possible values, see“NSKeyValueObservingOptions.” context Arbitrary data that is passed to anObserver in observeValueForKeyPath:ofObject:change:context:.
- 然后只要被观察者的keyPath值变化(注意:单纯改变其值不会调用此方法,只有通过getters和setters来改变值才会触发KVO),就会在观察者里调用方法observeValueForKeyPath:ofObject:change:context:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context Parameters keyPath The key path, relative to object, to the value that has changed. object The source object of the key path keyPath. change A dictionary that describes the changes that have been made to the value of the property at the key path keyPath relative to object. Entries are described in “Keys used by the change dictionary.” context The value that was provided when the receiver was registered to receive key-value observation notifications.
- 因此观察者需要实现方法 observeValueForKeyPath:ofObject:change:context: 来对KVO发出的通知做出响应。
- 这些代码都只需在观察者里进行实现,被观察者不用添加任何代码,所以谁要监听谁注册,然后对响应进行处理即可,使得观察者与被观察者完全解耦,运用很灵活很简便;但是KVO只能检测类中的属性,并且属性名都是通过NSString来查找,编译器不会帮你检错和补全,纯手敲所以比较容易出错。
- 2)NSNotification的使用
- 这里的通知不是由被观察者发出,而是由NSNotificationCenter来统一发出,而不同通知通过唯一的通知标识名notificationName来区分,标识名由发送通知的类来起。
- 首先被观察者自己在必要的方法A里,通过方法postNotificationName:object:来发出通知notificationName
- (void)postNotificationName:(NSString *)notificationName object:(id)notificationSender Parameters notificationName The name of the notification.
notificationSender The object posting the notification.
这样发送通知者这边的工作就完成了,每次A被调用,就会发送一次通知notificationName。
然后谁要监听A的变化,就通过[NSNotificationCenter defaultCenter]的方法addObserver:selector:name:object:为观察者注册监听name为notificationName的通知
- (void)addObserver:(id)notificationObserver selector:(SEL)notificationSelector name:(NSString *)notificationName object:(id)notificationSender Parameters notificationObserver Object registering as an observer. This value must not be nil.
notificationSelector Selector that specifies the message the receiver sends notificationObserver to notify it of the notification posting. The method specified by notificationSelector must have one and only one argument (an instance of NSNotification).
notificationName The name of the notification for which to register the observer; that is, only notifications with this name are delivered to the observer. If you pass nil, the notification center doesn’t use a notification’s name to decide whether to deliver it to the observer.
notificationSender The object whose notifications the observer wants to receive; that is, only notifications sent by this sender are delivered to the observer. If you pass nil, the notification center doesn’t use a notification’s sender to decide whether to deliver it to the observer.
然后每次发出name为notificationName的通知时,注册监听后的观察者就会调用其自己定义的方法notificationSelector来进行响应。
NSNotification的特点呢,就是需要被观察者先主动发出通知,然后观察者注册监听后再来进行响应,比KVO多了发送通知的一步,但是其优点是监听不局限于属性的变化,还可以对多种多样的状态变化进行监听,监听范围广,使用也更灵活。