您的位置:网站首页 > IT观察 > 正文

透彻理解 KVO 观察者模式(附基于runtime实现代码

类别:IT观察 日期:2018-6-1 14:14:15 人气: 来源:

  iOS开发中,有一种设计模式应用广泛,那就是观察者模式。苹果称其为 KVO(Key-Value Observing),既键值观察,总是有人把 KVC 和 KVO 混为一谈,实则它们只是名字长得像。相信看完本篇博客,并且看明白 github 中本人对其的代码实现,可以把 KVO 理解得更深刻。

  context是一个指针,用来准确匹配添加观察和接收观察,主要是在特定情况下无法区分该观察回调是否需要处理进行精确判断。

  change字典里面的new和old就是我们需要的值了,kind是关键径属性的类型标识,具体可以去看api。

  移除观察很简单,和移除通知比较类似,我们需要在不用继续观察的时候移除它,比如在控制器的dealloc方法里面,值得注意的是重复移除会 crash。

  KVO 是基于 runtime 运行时来实现的,当你观察了某个对象的属性,内部会生成一个该对象所属类的子类,然后从写被观察属性的setter方法,当然在重写的方法中会调用父类的setter方法从而不会影响框架使用者的逻辑,之后会将该对象的isa指针指向新创建的这个类,最后会重写-(Class)class;方法,让使用者通过[obj class]查看当前对象所属类的时候会返回其父类,达到移花接木的目的。

  看到了么,我们使用object_getClass ()方法成功躲开了 KVO 的障眼法,发现添加观察过后,_obj的类变成了NSKVONotifying_TestObj,在移除观察过后,_obj的类又变回TestObj。同时,我们还观察了setAName:方法的地址,发现同样是有变化,同样验证了重写setter方法的逻辑。

  通过这一块小代码,就基本可以验证以上的原理(当然更详细的分析可看Mike Ash大神的那篇文章)。

  通过前面两节的分析,相信都会有一点思了。本人对其的实现尽量符合原生的逻辑,但是出于各种原因,有些地方是不一样的,比如我没有采取使用响应链的方式回调,而是单个回调不会有依赖;对于非 id 类型的观察源码里面没有做处理,因为感觉太累了,偷个懒。不过这些都不是重点,核心逻辑才是重点。

  嗯,方法很熟悉,只是加了一个前缀,对于最后这个回调的方法,分类里面肯定是不会实现的,为了去除,在实现文件的这个地方加了一个忽略操作:

  这一步做了两件事,一是找到最终观察的对象及其属性,这和苹果 KVO 的做法不太一样,如果你做个试验就会知道,苹果的实现会将 keypath 所有涉及的对象都更换一个动态实现的子类,当然,我这里这么做一是为了减少复杂的判断,也是为了更清晰的实现 KVO;二是将回调需要的信息绑定在观察的对象上,当然,这里的数据结构实现上有点小复杂。

  其实了解 runtime 底层方法的朋友应该看起来比较轻松,不太会 runtime 的朋友可以搜索对应的方法了解其用法,当你熟悉一下之后发现并没有那么难。这里需要提出的是,给一个类添加方法有两种方式,一种是class_addMethod ()方法,一种是imp_implementationWithBlock ()block的方式。在生成派生类的时候,一定要判断是否当前对象 isa 指针已经指向了派生类了。若想看细看具体实现,还是下载demo。

  当然,我这里三两句话说完,实际上写这一段核心代码花了不少时间,纠结了各种方法的含义过后,才逐步完善容错机制。

  值得注意的是,objc_msgSendSuper方法调用现在必须要强转一下,objc_super是父类的一个结构体,receiver指向当前对象。在调用父类方法之前,使用KVC方式就可以拿到old值,在调用父类方法之后该值就会改变。

  可能大家也注意到,这里有个callBack函数,这里就是回调的逻辑了,这个就不贴出来了,主要就是通过getter方法的名字拿到当前类的回调消息,然后同时根据options做相应的处理。

  注意变量_context是一个指针,特意写了两个方法来读写它,在dealloc中将其指针内存的值清除。

  KVO 的原理看起来简单,实际上实现起来有一定的难度,特别是核心部分,需要使用一些观感不好的底层方法。还有就是对回调信息保存的数据结构,个人认为代码中的处理方式已经是效率比较高的了(当然这里主要考虑了时间复杂度)。

  通过对KVO的实现,本人对其的理解更加深入了,这不失为一种学习方法,探究苹果工程师的设计思,乐在其中,获益匪浅。

  本文由iOS开发授权爱尖刀发表,并经 爱尖刀 编辑。转载此文章须经作者同意,并请附上出处(爱尖刀)及本页链接。原文链接

  相关文章因未来而,为生活而触达,「进取号…防盗背包,拥有拉链还防刮!再也不…Windows藏得很深的设置项,打开速度快10倍心形朋友圈视频,朋友圈90%的人都在玩数据可视化的七大趋势手把手教你用Python库Keras做预测(附代…iOSDevTip作者我还没有学会写个人说明!文章188

0
0
0
0
0
0
0
0
下一篇:没有资料

相关阅读

网友评论 ()条 查看

姓名: 验证码: 看不清楚,换一个

推荐文章更多

热门图文更多

最新文章更多

关于联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助

声明:网站数据来源于网络转载,不代表站长立场,如果侵犯了你的权益,请联系站长删除。

CopyRight 2010-2016 科技创新信息网- All Rights Reserved