简单了解KVO底层的实现逻辑
示例代码
OC当中的KVO使用起来很简单,简单3个步骤就可以完成对一个对象的成员变量的监听;
假如我们想监听Persen对象的age属性:
// 1.给Person对象添加KVO监听
NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
[self.person addObserver:self forKeyPath:@"age" options:options context:@"123"];
// 2. 监听对象的属性发生改变时的回调函数
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{}
// 3.移除监听
[self.person removeObserver:self forKeyPath:@"age"];
KVO实现的本质
-
依然以Persen对象为例,正常情况下,self.person这个实例对象的isa指针,指向的应该是Person这个类对象;但是当给其添加KVO监听后,会在self.person这个instance对象和Person class对象之间,生成一个Person class的子类NSKVONotifying_Person;这时实例对象的isa指针,就会更改为指向NSKVONotifying_Person这个class对象;
NSKVONotifying_Person是Runtime动态创建的一个类,是Person的子类; 其内部包含class方法,返回值可能为[Person class]父类class
-
那么NSKVONotifying_Person是如何实现监听的过程呢?
// 以下均为伪代码,方便理解
- (void)setAge:(int)age {
// 在执行set方法时,会调用c函数中的下面这个方法
_NSSetIntValueAndNotify(); // 当然不仅仅有int的方法,char、long long、double...都有
}
void _NSSetIntValueAndNotify() {
[self willChangeVlaueForKey:@"age"];
[super setAge:age]; // 调用父类Person的setAge方法
[self didChangeValueForKey:@"age"];
}
- (void)didChangeValueForKey:(NSString *)key {
// 通知监听器,属性值发生了改变
[observer observeValueForKeyPath: key ofObject:self change:change context:nil];
}
阅读量
loading...