iOS KVO的实现原理
来源:互联网 发布:javascript 转义符 编辑:程序博客网 时间:2024/05/17 04:13
一、KVO是什么
- KVO是OC的一种观察者设计模式,另一种是通知机制(notification)
- KVO的机制:指定一个被观察对象,当该对象某个属性发生变化时,观察对象会获得通知,并作出相应动作,并且被观察的对象不需要添加任何额外的代码
在MVC设计架构下,KVO机制通常实现数据模型和视图之间的通讯,这样可以保证数据和视图显示达到同步
二、实现原理
KVO的实现依赖于OC强大的运行时Runtime。
原理:
当观察某对象时,KVO动态创建该对象的子类,并重写子类被观察属性setter方法,随后通知观察者该属性的变化状况。
实现过程:
Apple使用isa混写(isa-swizzling)来实现KVO。
当观察对象A时,KVO动态创建了新的名为NSKVONotifying_A的新类,该类时为对象A的子类,并且KVO重写了新类的观察属性的setter方法,setter方法负责在调用原setter方法之前和之后,通知所有观察者该属性的变化情况
- NSKVONotifying_A
每个对象内部都有isa指针,这个指针指向该对象的类,在KVO机制中,该isa指针被修改为指向系统新创建的子类NSKVONotifying_A,那么当被观察者修改被检测的属性的值时候,就会调用KVO重写的setter方法,从而激活键值通知机制,实现当前类属性改变的监听。
所以当我们从应用层面上来看,并没有意识到有新类的出现,这是apple隐瞒类对KVO的底层实现过程,而我们还以为是原来的类,但是此时如果我们创建一个新的名为“NSKVONotifying_A“的类时,就会发现系统运行到注册KVO的那段代码时,程序发生崩溃,因为系统在注册监听的时候动态创建了名为NSKVONotifying_A的中间类,并指向这个中间类了
- 子类重写setter方法
KVO的键值观察通知依赖于NSObject的两个方法:willChangeValueForKey:和didChangeValueForKey:,在存取数值的前后分别调用2个方法;
被观察属性发生改变之前,willChangeValueForKey:被调用,通知系统该keyPath的属性值即将变更;当改变发生后,didChangeValueForKey:被调用,通知系统keyPath的属性值已经发生改变,之后,observeValueForKey:ofObject:change:context:也会被调用。
注意:重写观察属性的setter方法这种继承方式的注入是在运行时而不是编译时实现的
KVO为子类的观察者属性重写调用存取方法的工作原理在代码中相当于:
-(void)setName:(NSString *)newName{ [self willChangeValueForKey:@"name"]; //KVO在调用存取方法之前总调用 [super setValue:newName forKey:@"name"]; //调用父类的存取方法 [self didChangeValueForKey:@"name"]; //KVO在调用存取方法之后总调用}
三、特点
观察者观察的是属性,只有遵循KVO变更属性值的方式才会执行KVO的回调方法,例如执行setter方法、KVC方式赋值等,如果赋值没有通过KVO来变更属性值,而是直接修改属性对应的成员变量,例如:仅调用_name=@”newName”,这时是不会触发KVO机制,更加不会调用回调方法的,因此,使用KVO机制的前提是遵循KVO属性设置方式来变更属性值。
四、拓展
1、和KVC的比较?
- KVC,即Key-Value-Coding,是一个非正式协议,使用字符串(key)来访问一个对象实例变量的机制
- KVO,即Key-Value-Observing,它提供一种机制,当被观察者的属性值更改时,观察者就会接收到通知
2、和通知的区别?
- 相比于KVO重写setter时调用 observeValueForKey:ofObject:change:context:方法,通知要多发送通知操作,例如重写类的setter方法,使用通知也可以实现类似KVO的监听
- 两者都是一对多,两者相比,通知的使用率要高得多,因为通知监听不局限于属性的变化,还可以是状态的变化,监听范围广,例如键盘的出现、app进入后台等,使用也更灵活方便
- KVO的过程其实包括了通知这一环,只不过由系统来完成了
3、和delegate的不同?
KVO、通知、delegate三者都是类与类之间的通信,但是delegate不同的是:
- KVO和通知都负责发送和接收通知,剩下的事情都由系统来完成,所以不用返回值,而delegate则需要协议和代理对象来关联
- delegate适用于一对一,KVO和通知则适用于一对多情况
4、涉及的技术
KVC和KVO实现的根本是OC语言的动态性和运行时runtime,以及访问器方法的实现
五、总结
相比如其他消息回调的方式,KVO机制的实现更多的依赖于系统支持,它能够提供被观察属性的newValue和oldValue;但是由于需要创建对应的子类、重写setter方法等,内存消耗也是很大的,所以对于两个类之间的消息通信,我们应该根据实际应用的场景来选择通信方式
另外需要注意的是,由于这中继承方式的注入是在运行时而非编译时实现,所以当没有观察者时,KVO不会有任何开销,此时也根本就没有KVO代码存在,但是如果时委托和通知那还是需要开销,这也是KVO零开销观察的优势。
六、文章转载地址
iOS–KVO的实现原理与具体应用
- iOS KVO的实现原理
- iOS KVO 实现原理
- iOS-KVO 实现原理
- iOS的KVO底层实现原理
- iOS中KVO的底层实现原理
- iOS ---- KVO的内部实现原理
- iOS ---- KVO的内部实现原理
- iOS中KVO的实现原理
- ios KVO的使用和原理实现
- iOS kvo 底层实现原理
- iOS KVO底层实现原理
- KVO的实现原理
- KVO的实现原理
- KVO的实现原理
- KVO 的实现原理
- iOS--KVO的实现原理与具体应用
- iOS开发-- KVO的实现原理与具体应用
- iOS--KVO的实现原理与具体应用
- hdu 5894 (组合)
- Fibonacci (矩阵快速幂)
- 仿京东首页的京东快报,自动向上滚动的广告条
- C#之入门总结_lamba,接口策略表达式排序 _22
- java有关异常的分析
- iOS KVO的实现原理
- Android Studio代码混淆
- IO流--RadomAccessFile类
- spring 定时任务
- Python语法基础13.列表
- 整数转罗马和罗马转整数
- Tr A(矩阵快速幂)
- HDU
- 一个类的六个默认函数