美文网首页
4.2 KVC/KVO —— KVO的底层原理

4.2 KVC/KVO —— KVO的底层原理

作者: 哈库呐玛塔塔__ | 来源:发表于2020-05-13 02:25 被阅读0次

1.KVO的实现原理

当你调用addObserver去观察一个实例对象时,runtime会动态创建一个叫做NSKVONotifying_<原类名>的新类,它继承自该实例对象的原本的类,并重写了新类中被观察属性的setter方法。重写的setter方法会负责在调用super的setter方法之前和之后,(所以,setter方法的调用并不是通过hook,而是通过继承)通知所有观察对象值的更改。具体set方法如何重写,看下边的2。

在这里边有个细节,在添加观察者,动态创建NSKVONotifying_<原类名>之后,会将原类的isa指针指向这个动态创建的新类,所以当你调用原类的set方法时实际上调用的是NSKVONotifying_<原类名>的set方法。然后NSKVONotifying_<原类名>里的class方法,返回的是原类的类名,这是苹果并不希望把NSKVONotifying_<原类名>这个类暴露出来,屏蔽内部实现,隐藏这个类的存在。

其实简单的思路其实就是在set方法前后分别加上willChangeValueForKey:和didChangeValueForKey:这两个方法,而对变化做出处理的observeValueForKeyPath:方法的调用实际上也就是在方法didChangeValueForKey:中被调用的。

手动触发valueChange  还需要重写一个automaticallyNotifiesObserversForKey方法,将需要检测的属性的自动监测判断改为NO

那么“手动触发”的使用场景是什么?一般我们只在希望能控制“回调的调用时机”时才会这么做。

或者属性被声明为readonly。那么在子类中通过@synthesize重写该变量的时候,对其进行赋值的时候就需要手动触发,因为readonly不可以调用set方法

    返回NO就说明age的监测 由手动控制只有成对调用willchage 和 didChange 方法时 才会 触发KVO。  如果不重写这个方法,那么通过set赋值 和 willChange/didChange 方法都会触发KVO

2.说说KVO怎么重写的set方法

首先获取该属性的旧值。然后给动态创建的NSKVONotifying_<原类名>这个类的父类,也就是我们能看到的被观察的对象,发送set新值的消息。最后给所有观察者发送消息,告诉其属性值已经改变。也就是调用observeValueForKeyPath:方法。

如何对数组实现KVO

举个例子,myItems 是我们要进行 KVO 的一个属性,它的定义如下:

@property (nonatomic, strong) NSMutableArray *myItems;

在它进行添加元素时,使用如下方法:

[[self mutableArrayValueForKey:@"myItems"] addObject:item];

这样,我们便实现了对 NSMutableArray 的 KVO。

何时触发

1. 直接调用set方法,或者通过属性的点语法间接调用

2.使用KVC的setValue:forKey:方法

3. 使用KVC的setValue:forKeyPath:方法

4.通过mutableArrayValueForKey:方法获取到代理对象,并使用代理对象进行操作

参考文章:

https://www.jianshu.com/p/7ff5ffb31ead

https://www.jianshu.com/p/d0032fd9397b

https://tech.glowing.com/cn/implement-kvo/

相关文章

网友评论

      本文标题:4.2 KVC/KVO —— KVO的底层原理

      本文链接:https://www.haomeiwen.com/subject/olawnhtx.html