前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >KVO的实现原理

KVO的实现原理

作者头像
CC老师
发布2022-03-15 08:07:03
1.2K0
发布2022-03-15 08:07:03
举报
文章被收录于专栏:HelloCode开发者学习平台

什么是KVO

KVO 就是 Key-Value Observing,就是键值观察。它是一种观察者模式的衍生。其基本思想是,对目标对象的某属性添加观察,当该属性发生变化时,通过触发观察者对象实现的KVO接口方法,来自动的通知观察者。

KVO实现原理

以下代码为p对象的name属性添加了KVO观察。然后在添加观察前下个断点。

通过lldb调试可以看到,在执行addObserver方法之前,p对象Class类型为LGPerson。

好,在执行完addObserve这行代码之后,p对象Class类型就变成了

NSKVONotifying_LGPerson。

那这个NSKVONotifying_LGPerson和LGPerson有什么关系呢?

或者说这个NSKVONotifying_LGPerson是本来就存在的还是动态生成的呢?

没有关系,我们来测试一下。

然后再27行代码出下断点调试。

这就说明,这个NSKVONotifying_LGPerson并不是一开始存在,而是通过addObserve这行代码动态生成的。

NSKVONotifying_LGPerson是LGPerson的子类。

在移除观察者代码处下俩个断点。

通过打印信息我们可以发现addObserve的时候,self.p的isa指针指向了

NSKVONotifying_LGPerson,在removeObserver之后,self.p的isa指针又指回了

LGPerson。

NSKVONotifying_LGPerson类会自动生成几个方法,如下图所示。

关键是这个setName方法。实现功能依赖的就是这个setName。

那这个setName方法究竟做了啥呢?

我们首先下俩个断点。在26行代码处lldb输入watchpoint set variable self->_p->_name。

watchpoint set variable观察某个值是否修改

然后过掉26行代码断点。我们28行代码处给self.p.name赋值的时候,代码就被断住了。

大家可以看到,在给self.p.name赋值之前,也就是调用p的setName方法之前,系统还调用了下面这俩个方法。

这个方法里面有NSKeyValueWillChange和NSKeyValueDidChange。

这也是为什么观察成员变量变化不生效的原因。因为并不会生成setter方法

那为什么成员变量用setValue:forKey的方式就能观察到,产生相应的回调呢。

这个需要用到GNUstep的源码,虽然GNUstep不是苹果官方的源码,但是还是有很高的参考价值的

在GNUstep搜索observeValueForKeyPath

表示被观察对象收到了一个 -setValue:forKey:消息,或者键值编码兼容的设置方法键已被调用,

或者 -willChangeValueForKey:

或-didChangeValueForKey:对已被调用。

但是需要注意一点:willChangeValueForKey和didChangeValueForKey一定要成对出现。

那observeValueForKeyPath是什么时候调用的呢?

是通过notifyForKey方法。

在didChangeValueForKey方法里面就会调用notifyForKey方法来触发

observeValueForKeyPath的回调。

总结

所以,KVO的实现原理为:在我们调用addObserve的时候,会动态生成一个以NSKVONotifying_开头的当前类的一个子类,对象的isa指针就会指向这个类,系统会自动生成相应的方法。

这个系统生成的子类回去调用对应的setter方法,在这个setter方法的内部,其实就是调用

willChangeValueForKey和didChangeValueForKey这俩个方法。

然后在didChangeValueForKey方法内部会调用notifyForKey方法来触发

observeValueForKeyPath的回调。

- END -

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-01-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 HelloCoder全栈小集 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是KVO
  • KVO实现原理
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档