KVO
KVO全称是Key-Value Observing, 用于监听对象属性值的变化
KVO的使用
- 给一个对象的属性添加KVO
[p addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
复制代码
- 实现KVO的方法, 来监听属性值的变化
/**
keyPath: 被观察的属性的key
object: 被观察的对象
change: 属性的改变对象
context: 上下文
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
NSLog(@"监听到了%@的%@属性发生了改变", object, keyPath);
NSLog(@"%@", change);
}
复制代码
KVO的原理
- 在iOS底层, 是通过isa-swizzling 来实现的. 当我们给对象A添加KVO时, 就会动态创建一个名字为 NSKVONotifying_A的类, 这个类继承自A的本类.
- 对象A的isa指针从A类指向NSKVONotifying_A, NSKVONotifying_A的superclass指针指向A类.
- 在NSKVONotifying_A中重写 setter方法, 在其中做一些KVO相关的处理
- 当我们修改A对象属性时, 会通过isa指针找到NSKVONotifying_A类中的方法列表, 执行NSKVONotifying_A重写过的setter方法, 来实现KVO的处理
我们可以通过打印isa指针来郑明这一点
KVO如何重写setter方法
通过上边的分析, 我们可以猜测KVO重写的setter方法可能为:
- (void)setName:(NSString *)name {
[self willChangeValueForKey:@"name"];
// 这里会进行修改name的值
[self didChangeValueForKey:@"name"]; // 触发 observeValueForKeyPath: 方法, 回调给观察者
}
复制代码
KVC
KVC全称是Key-Value Coding, 可以通过字符串key来访问对象的某个属性
KVC的使用
常用的KVCAPI有:
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (void)setValue:(id)value forKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
- (id)valueForKey:(NSString *)key;
复制代码
setValue:forKey: 查找的过程
- 根据key查找: setKey, _setKey方法, 调用setter方法
- 查看accessInstanceVariablesDirectly函数的返回值,如果是NO, 进行第4步.(默认是YES)
- 查找_key、_isKey、key、isKey的成员变量, 进行赋值
- 调用setValue:forUndefinedKey:, 并抛出异常NSUnknownKeyException
valueForKey: 查找的过程
- 查找getKey、key、 isKey、_key方法, 调用getter方法
- accessInstanceVariablesDirectly函数的返回值,如果是NO, 进行第4步.(默认是YES)
- 查找_key、_isKey、key、isKey的成员变量, 直接取值
- 调用valueForUndefinedKey:, 并抛出异常NSUnknownKeyException
KVC与KVO
- 我们直接, 给一个属性赋值可以触发KVO, 那么通过KVC可以么? 可以
- 直接给对象的成员变量赋值, 可以触发KVO么? 不可以
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END