探索KVO的本质(二)

31 篇文章 0 订阅
2 篇文章 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的本质.

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

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值