KVO面试题
概念
KVO(Key-Value-Observer)也就是观察者模式,是苹果提供的一套事件通知机制。允许对象监听另一个对象特定属性的改变,并在改变时接收到事件,一般继承自NSObject的对象都默认支持KVO。
KVO和NSNotificationCenter的区别
KVO和NSNotificationCenter都是iOS中观察者模式的一种实现。区别在于:
1、相对于被观察者和观察者之间的关系,KVO是一对一的,而不一对多的。也就是kvo监听到被观察属性值改变时只会通知到观察者,是一对一的关系。而通知模式则是在被观察值改变的时候发送全局通知,任何对象都可以接听到这个通知,是一个一对多的关系;
2、KVO对被监听对象无侵入性,不需要修改其内部代码即可实现监听。而通知需要在被监听对象改变的时候添加发送通知代码。
KVO的使用步骤
1.对象添加监听器,监听某个属性
2.改变对象的属性
3.调用系统监听方法
4.监听完毕,消除监听器
KVO实现原理
1、当实例对象 进行KVO观察时候,会利用RuntimeAPI动态生成一个子类,然后将对象的isa指向新生成的子类
2、KVO本质上是监听属性的setter方法,只要被观察对象有成员变量和对应的set方法,就会调用Foundation的_NSSetValueAndNotify函数这个函数内部会执行 willChangeVlaueForKey函数、父类的setter方法 和didChangeVlaueForKey的方法(didChangeVlaueForKey 方法内部会触发监听器的observeValueForKeyPath: ofObject: context:函数
3、子类会重写父类的set、class、dealloc、_isKVOA方法
4、当观察对象移除所有的监听后,会将观察对象的isa指向原来的类
5、当观察对象的监听全部移除后,动态生成的类不会注销,而是留在下次观察时候再使用,避免反复创建中间子类
KVO的优缺点
优点:
1.能够提供一种简单的方法实现两个对象间的同步
2.能够对非我们创建的对象,即内部对象的状态改变做出响应,而且不需要改变内部对象的实现
3.能够提供观察的属性的最新值以及先前值
4.用key paths来观察属性,因此也可以观察嵌套对象
5.完成了对观察对象的抽象,因为不需要额外的代码来允许观察值能够被观察
缺点:
1.我们观察的属性必须使用string来定义,因此在编译期不会出现警告以及检查
2.对属性重构将导致我们的观察代码不再可用
3.复杂的if 语句要求对象正在观察多个值,这是因为所有的观察代码通过一个方法来指向
4.当释放观察者时需要移除观察者
KVO的使用场景:
- 实现上下拉刷新控件 content offset
- webView 混合排版 content size
- 监听模型属性实时更新UI
直接修改成员变量(不同于属性,没有setter方法)是否会触发KVO?
1,不会,因为KVO本质是替换属性的setter方法;
2,如果要手动触发,在修改成员值前后,要多调用willChangeValueForKey,,和didChangeValueForKey即可
如何手动触发KVO
- 手动触发的前提是这个对象已经添加了kvo 如果没有添加的话kvo是无法知道观察者是谁的
- 调用willChangeValueForKey和didChangeValueForKey