kvo底层的一些实现
2016-06-09 00:00
288 查看
一直痴痴地使用kvo,一直想了解一下其实现机制。
1.kvo的基本思想
kvo的来源于设计模式其中的观察者模式,观察者模式将观察者和被观察者之间的耦合度降低。我自己理解为观察者模式是kvo的大纲,也解释了为什么我们要手动单独实现回调方法。它本身的一个思路为被观察对象在自身状态改变的时候,通知观察者。通知是调用观察者对象类中的接口方法实现。
想想我刚开始接触kvo是,傻傻的分不清楚,跟着网上指导,先注册,后回调方法,再移除。写完后懵逼依旧,第二次想用,打开火狐浏览器,输入 kvo的使用,点击,然后再傻不愣登的学半天,吃个饭回来又忘了当下菜用了。
其实按照设计模式的思路理解能更好的理解,为什么要这么一步步的干。
2.kvo实现的要素
通过以下两个方法可以实现观察时的注册和移除,但要实现kvo是有条件的。
曾经有人给我告白,kvo的实现需要有setter方法。那时候,听到以后自己是懵逼的,在看了许多资料后才有一点点思路。
将观察者和被观察者注册好之后,被观察着满足以下两个条件任何一种,观察着才会得到通知。
a、遵循使用属性的setter方法,也就是说,此属性需要有setter方法。当使用@property时,系统自动为我们生成了sette方法,此时我们可以直接使用。但当使用实例变量的方式的时候,需要我们自己重写setter方法。
b、当没有setter方法的时候我们需要通过key-path这个方法来设置。如下:
3.kvo的实现原理
从我认识kvo那天起,就一直很奇怪一个问题。明明我自己在写类中的属性的时候并没任何关于观察的代码,实现观察的东西是怎么添加上去的。在学习到runtime的时候,才懂了,kvo的实现离不开强劲的runtime。下面我们一步步来:
a、kvo会生效其内部的方法和逻辑,其原因为下面两个方法:
两个方法用于通知系统观察的属性即将要变和已经变完,这两个方法被写入属性的setter方法中。
b、kvo的添加
当我们使用kvo进行观察的时候,系统已经重写了对应属性的setter方法。系统做了两件事情:
第一件为当我们对相关属性进行观察的时候,利用runtimer帮我们生成一个派生类,这个类是对被观察者对象中isa指针指向类的一个扩充(如果不清楚isa指针、实例对象、类、元类、根元类可以暂且理解为对系统利用runtime帮我们生成了一个比被观察者对象类更强大的类)。扩充的内容就是重写相关属性(注册观察的属性)的setter方法,就类似于a中对setter方法的处理一样。
第二件为系统接近于“卑鄙下流(开个玩笑)”的连哄带骗的使用它自己生成的派生类代替我们原先自己的类。其连哄带骗的方式为利用runtime动态的修改了isa指针指向的类。从而导致于我们通过setter方法改变属性值的时候,其调用的方法为系统帮我们重写setter方法即为派生类中的setter方法。此方法中有关于观察通知的相关方法,从而触发一些列事件。
注:如果对替换过程有兴趣的,可以了解runtime动态创建对象和如何替换对象。
至此就是kvo的添加过程,如果有出错的地方,十分欢迎指出,经常被打脸,再被打中成长。
1.kvo的基本思想
kvo的来源于设计模式其中的观察者模式,观察者模式将观察者和被观察者之间的耦合度降低。我自己理解为观察者模式是kvo的大纲,也解释了为什么我们要手动单独实现回调方法。它本身的一个思路为被观察对象在自身状态改变的时候,通知观察者。通知是调用观察者对象类中的接口方法实现。
想想我刚开始接触kvo是,傻傻的分不清楚,跟着网上指导,先注册,后回调方法,再移除。写完后懵逼依旧,第二次想用,打开火狐浏览器,输入 kvo的使用,点击,然后再傻不愣登的学半天,吃个饭回来又忘了当下菜用了。
其实按照设计模式的思路理解能更好的理解,为什么要这么一步步的干。
2.kvo实现的要素
通过以下两个方法可以实现观察时的注册和移除,但要实现kvo是有条件的。
[code=language-objectivec]- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context; - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
曾经有人给我告白,kvo的实现需要有setter方法。那时候,听到以后自己是懵逼的,在看了许多资料后才有一点点思路。
将观察者和被观察者注册好之后,被观察着满足以下两个条件任何一种,观察着才会得到通知。
a、遵循使用属性的setter方法,也就是说,此属性需要有setter方法。当使用@property时,系统自动为我们生成了sette方法,此时我们可以直接使用。但当使用实例变量的方式的时候,需要我们自己重写setter方法。
b、当没有setter方法的时候我们需要通过key-path这个方法来设置。如下:
[code=language-objectivec] [class setValue:30 forKey:@"age"];
3.kvo的实现原理
从我认识kvo那天起,就一直很奇怪一个问题。明明我自己在写类中的属性的时候并没任何关于观察的代码,实现观察的东西是怎么添加上去的。在学习到runtime的时候,才懂了,kvo的实现离不开强劲的runtime。下面我们一步步来:
a、kvo会生效其内部的方法和逻辑,其原因为下面两个方法:
[code=language-objectivec]- (void)willChangeValueForKey:(NSString *)key; - (void)didChangeValueForKey:(NSString *)key;
两个方法用于通知系统观察的属性即将要变和已经变完,这两个方法被写入属性的setter方法中。
[code=plain]- (void) setAge:change { [self willChangeValueForKey:@"age"]; age = change; [self didChangeValueForKey:@"age"]; }
b、kvo的添加
当我们使用kvo进行观察的时候,系统已经重写了对应属性的setter方法。系统做了两件事情:
第一件为当我们对相关属性进行观察的时候,利用runtimer帮我们生成一个派生类,这个类是对被观察者对象中isa指针指向类的一个扩充(如果不清楚isa指针、实例对象、类、元类、根元类可以暂且理解为对系统利用runtime帮我们生成了一个比被观察者对象类更强大的类)。扩充的内容就是重写相关属性(注册观察的属性)的setter方法,就类似于a中对setter方法的处理一样。
第二件为系统接近于“卑鄙下流(开个玩笑)”的连哄带骗的使用它自己生成的派生类代替我们原先自己的类。其连哄带骗的方式为利用runtime动态的修改了isa指针指向的类。从而导致于我们通过setter方法改变属性值的时候,其调用的方法为系统帮我们重写setter方法即为派生类中的setter方法。此方法中有关于观察通知的相关方法,从而触发一些列事件。
注:如果对替换过程有兴趣的,可以了解runtime动态创建对象和如何替换对象。
至此就是kvo的添加过程,如果有出错的地方,十分欢迎指出,经常被打脸,再被打中成长。
相关文章推荐
- IE:添加编辑器
- Windows2003下批量添加和导出所有ip BAT脚本
- 使用 Iisext.vbs 添加Web服务扩展文件的方法
- 添加新的.Net的影射
- 结合PHP脚本添加和查询MySQL数据的基本教程
- C#实现为类和函数代码自动添加版权注释信息的方法
- asp.net Execl的添加,更新操作实现代码
- JavaScript实现为指定对象添加多个事件处理程序的方法
- JS实现动态给图片添加边框的方法
- javascript 添加和移除函数的通用方法
- 基于JavaScript实现动态添加删除表格的行
- jQuery使用after()方法在元素后面添加多项内容的方法
- jQuery给多个不同元素添加class样式的方法
- jQuery使用append在html元素后同时添加多项内容的方法
- jquery 如何动态添加、删除class样式方法介绍
- jQuery实现动态添加和删除一个div
- asp.net两级联动(包含添加和修改)
- JSP实现添加功能和分页显示实例分析
- jQuery动态添加及删除表单上传元素的方法(附demo源码下载)
- JSP+Ajax 添加、删除多选框