KVO实现原理
来源:互联网 发布:域名注册哪里好 编辑:程序博客网 时间:2024/05/21 19:35
KVO(Key Value Observing),是观察者模式
在Foundation
中的实现
KVO的原理
简而言之就是:
- 当一个object有观察者时,动态创建这个object的类的子类
- 对于每个被观察的property,重写其
set
方法 - 在重写的
set
方法中调用- willChangeValueForKey:
和- didChangeValueForKey:
通知观察者 - 当一个property没有观察者时,删除重写的方法
- 当没有observer观察任何一个property时,删除动态创建的子类
空说无凭,简单验证下。
@interface Sark : NSObject@property (nonatomic, copy) NSString *name;@end@implementation Sark@end
测试代码:
Sark *sark = [Sark new];// breakpoint 1[sark addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];// breakpoint 2sark.name = @"萨萨萨";[sark removeObserver:self forKeyPath:@"name"];// breakpoint 3
断住后分别使用- class
和object_getClass()
打出sark
对象的Class和真实的Class
// breakpoint 1(lldb) po sark.classSark(lldb) po object_getClass(sark)Sark// breakpoint 2(lldb) po sark.classSark(lldb) po object_getClass(sark)NSKVONotifying_Sark// breakpoint 3(lldb) po sark.classSark(lldb) po object_getClass(sark)Sark
上面的结果说明,在sark对象被观察时,framework使用runtime
动态创建了一个Sark类的子类NSKVONotifying_Sark
而且为了隐藏这个行为,NSKVONotifying_Sark重写了- class
方法返回之前的类,就好像什么也没发生过一样
但是使用object_getClass()
时就暴露了,因为这个方法返回的是这个对象的isa
指针,这个指针指向的一定是个这个对象的类对象
然后来偷窥一下这个动态类实现的方法,这里请出一个NSObject的扩展NSObject+DLIntrospection
,它封装了打印一个类的方法、属性、协议等常用调试方法,一目了然。
@interface NSObject (DLIntrospection)+ (NSArray *)classes;+ (NSArray *)properties;+ (NSArray *)instanceVariables;+ (NSArray *)classMethods;+ (NSArray *)instanceMethods;+ (NSArray *)protocols;+ (NSDictionary *)descriptionForProtocol:(Protocol *)proto;+ (NSString *)parentClassHierarchy;@end
然后继续在刚才的断点处调试:
// breakpoint 1(lldb) po [object_getClass(sark) instanceMethods]<__NSArrayI 0x8e9aa00>(- (void)setName:(id)arg0 ,- (void).cxx_destruct,- (id)name)// breakpoint 2(lldb) po [object_getClass(sark) instanceMethods]<__NSArrayI 0x8d55870>(- (void)setName:(id)arg0 ,- (class)class,- (void)dealloc,- (BOOL)_isKVOA)// breakpoint 3(lldb) po [object_getClass(sark) instanceMethods]<__NSArrayI 0x8e9cff0>(- (void)setName:(id)arg0 ,- (void).cxx_destruct,- (id)name)
首先就有个扎眼的- .cxx_destruct
冒出来,这货是个啥?详细的探究请参考我的另一篇文章。
大概就是说arc下这个方法在所有dealloc
调用完成后负责释放所有的变量,当然这个和kvo没啥关系了,回到正题。
从上面breakpoint2的打印可以看出,动态类重写了4个方法:
- setName:
最主要的重写方法,set值时调用通知函数- class
隐藏自己必备啊,返回原来类的class- dealloc
做清理犯罪现场工作- _isKVOA
这就是内部使用的标示了,判断这个类有没被KVO动态生成子类
接下来验证一下KVO重写set方法后是否调用了- willChangeValueForKey:
和- didChangeValueForKey:
最直接的验证方法就是在Sark类中重写这两个方法:
@implementation Sark- (void)willChangeValueForKey:(NSString *)key { NSLog(@"%@", NSStringFromSelector(_cmd)); [super willChangeValueForKey:key];}- (void)didChangeValueForKey:(NSString *)key { NSLog(@"%@", NSStringFromSelector(_cmd)); [super didChangeValueForKey:key];}@end
没问题。
0 0
- 解析KVO实现原理
- 解析KVO实现原理
- 解析KVO实现原理
- KVO的实现原理
- KVO实现原理探究
- KVO底层实现原理
- KVO底层实现原理
- KVO实现原理
- KVO实现原理
- KVO实现原理
- 解析KVO实现原理
- KVO实现原理
- KVO的实现原理
- KVO实现原理
- KVO实现原理
- KVO的实现原理
- KVO 的实现原理
- iOS KVO 实现原理
- 二行代码解决全部网页木马
- photoshop切片输出gif出现白边
- Photoshop制作超酷的金属立体字
- 网页简体转繁体的JS代码
- 跳转菜单如何实现新窗口打开连接
- KVO实现原理
- 二级收缩菜单,点击出现二级菜单
- Illustrator制作透明质感立体方块…
- 图片多方向滚动控制效果
- 一个去掉HTML格式的ASP函数
- 取标题多少字数,多出加上省略号
- WebView使用详解(一)——Native与JS相互调用(附JadX反编译)
- 在某范围内的内容(包括图片、文字)…
- XP环境下查看psd文件缩略图显示补…