KVO(Key-Value-Observing)
一对多,观察者模式,俗称”键值监听“,可以用于监听某个对象属性值的改变。
当观察一个对象时,runtime会动态创建一个继承自该对象的类,并重写被观察对象的setter方法,重写的setter方法会负责在调用原setter方法前后通知所观察对象值的更改,最后把该对象的isa指针指向这个新建的子类,对象就变成了子类的实例。过程如下:
1>会调用foundation的NSSetXXXValueAndNotify函数
2>函数内部实现
- willChangeValueForKey
- 父类原来的Setter
- didChangeValueForKey(内部会触发监听器的监听方法(observeValueForKeyPath:ofObject:change:context:))
如何手动触发KVO
在Setter方法里,手动实现NSObject的两个方法:
- willChangeValueForKey
- didChangeValueForKey
KVC(Key-Value-Coding)
俗称”键值编码“,可以通过一个key来访问属性,常见的API有:
-(void)setValue:(id)value forKey:(NSString *)key;
-(void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (id)valueForKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
1.setValueForKey原理
1>按照setKey、_setKey顺序查找方法,找到了就传递参数,调用方法
2>如果没找到,就判断(BOOL)AccessInstanceVariablesDirectly函数是否返回Yes,如果返回Yes,就按照_key、_isKey、_key、_iskey顺序查找成员变量,找到了成员变量就直接赋值。找不到成员变量,调用setValue:forUndefinedKey并抛出异常NSUnknownKeyException
2.valueForKey原理
1>调用getter方法,按照getKey、key、isKey、_key顺序查找,如果找到,则直接返回对应的值
2>如果找不到,判断+(BOOL)AccessInstanceVariablesDirectly函数是否返回Yes,如果返回Yes,则访问成员变量_key、_isKey、_key、iskey。找到则返回对应的值,找不到则调用valueForUndefinedKey:抛出异常。
NotificationCenter
多对多,消息的发送者告知接收者事件已经发送或者将要发送,仅此而已,接受者并不能反过来影响发送者的行为。
Delegate
一对一,代理的目的是改变或者传递控制链。允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针。
可以减少框架的复杂度。消息的发送者告知接收者某个事件将要发生,Delegate同意然后发送响应事件,delegate机制使得接收者可以改变发送者的行为。
区别
效率肯定是delegate比NSNotification高
delegate方法比Notification更加直接,需要关注返回值,所以delegate方法往往包含should这个很传神的词。相反的,Notification最大的特色就是不关心结果。所以Notification往往用did这个词汇。
两个模块之间联系不是很紧密,就用Notification传值,例如多线程之间传值
delegate只是一种较为简单的回调,且主要用在一个模块上中,例如底层功能完好,需要把一些值传到上层去,就事先把上层的函数通过delegate传到底层,然后底层调用这个delegate。
网友评论