美文网首页
探索KVO的本质(二)

探索KVO的本质(二)

作者: GDCoder | 来源:发表于2021-03-13 17:37 被阅读0次

通过探索kvo的本质(一)我们已经了解到很多关于kvo的基础知识,接下来我们看下面的代码:

我们知道:通过[** class]和object_getClass(**) 都能获取实例对象的类对象,而从上面的运行结果,我们很容易知道,通过runtime的object_getClass(**)获取的就是它的真实的类对象,而[** class]获取的是它的什么?

还记得上一个博客的图吗?

这里直接说结论,是因为[self.person1 class],class方法由于看不到源码,但是我们可以猜测它的大概实现如下:

-(Class)class

{ return [GDPerson class] } 里面可能是这个实现,猜测大概是这样

其实这样也是不给开发者一个疑惑,也是屏蔽NSKVONotifying_GDPerson的内部实现,隐藏NSKVONotifying_GDPerson这个类,也是重写了这个方法,让[self.person1 class]返回的结果变成了GDPerson.

其实你可以查看[** class]这个方法(commad+jump)最终查找的就是NSObject,你这个对象是什么类型,返回的最终结果就是什么类型.

验证NSKVONotifying_GDPerson里面方法

有同学可能疑惑,你怎么知道NSKVONotifying_GDPerson里面会有setAge:,class;dealloc;isKVOA这些方法的存在呢?(也就是上面那张图绿色的部分),接下来我就证明这些方法的存在

证明这个需要用到运行时的一个函数:class_copyMethodList(<#Class  _Nullable __unsafe_unretained cls#>, <#unsigned int * _Nullable outCount#>),这个函数的描述就是获取类的方法,第一个参数就是类名,第二个涉及c语言的知识,这里就不直接过多描述,直接贴代码:

这里是不是瞬间感觉6666!😄,调用的时候我们需要传入真正的类对象也就是

[self printMethodNamesofClass:object_getClass(self.person1)];

这就证明了我们上面的疑问

总结结论:

1.iOS用什么方式实现对一个对象的KVO?(KVO的本质是什么?)

a.利用RuntimeAPI动态生成一个子类,并且让instance对象的isa指向这个全新的类

b.当修改instance对象的属性时,会调用Foundation的_NSSetXXXValueAndNotify函数

c.WillChangeValueForKey;父类原来的setter方法;didChangeValueForKey

d.内部会触发监听器(Oberser)的监听方法 oberserValueForKeyPath:ofObject:change:context

2.如何手动触发KVO?

手动调用willChangeValueForKey和didChangeValueForKey就行了

(这里大家可以尝试验证,只要执行didChangeValueForKey就会调用,因为执行did内部会验证will,所以要一起写,    [self.person1 willChangeValueForKey:@"age"]  [self.person1 didChangeValueForKey:@"age"];)

3.直接修改成员变量会不会触发KVO

不会触发kvo (只有执行了属性的set方法才会触发或者手动触动)

(这个不验证了,很简单,大家自己尝试)

接下来博客我会介绍kvc的本质.

如果觉得我写得对您有所帮助,请关注我,我会持续更新😄

相关文章

网友评论

      本文标题:探索KVO的本质(二)

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