iOS探究KVO底层并手写KVO

我们都知道苹果的KVO可以为我们提供观察属性的方法,它可以实现监听属性的改变并得到通知。既然苹果没有给我们开源,那我们就来自己琢磨一下它究竟是如何工作的。

1 kvo的使用

我们首先来写一个非常简单的kvo使用,当点击屏幕时,可以得到kvo通知回调,并且打印这个属性的新值。

这些都是基本的kvo使用,这里就不做过多介绍啦。。。

2 假设kvo的实现原理

那这里我们就要思考了,既然是观察属性的变化,那我们自然就会联想到setter方法,苹果可以重写这个类的setter方法,并且使用willChangeValueForKey和DidChangeValueForKey方法来监听属性并发送通知,当然又不可能直接加在People类里面,那么会不会是动态创建了一个类,继承这个People类,改变这个类的isa指针,并且重写属性的方法呢?既然有了思路,那就一起来试试看吧。

当然这么说也不是没有根据的,我们在kvo这句代码打个断点,就可以看到原本isa指针是People,而执行完成addObserver后就isa指针就变成了 NSKVONotifying_People,所以我们知道刚才的假设是成立的,虽然我们不能完全知道kvo底层到底是怎么实现的,不过却可以用所学知识来手动实现一个kvo。

3 手动实现kvo

既然要实现kvo这个方法,那么一定要有addObserver这个方法,通过Definition我们可以看到,addObserver这个方法是NSObject的一个分类。

那么我们也来模仿一下,给NSObject写一个分类,这里我准备分4步来实现。

1.创建被观察者的子类

2.修改调用者isa指针

3.重写子类的set方法

4.发送通知

1、创建被观察者的子类

首先我们创建一个NSObject的分类,给这个分类添加一个方法,由于不能和已经存在的addObserver方法重名,我就在addObserver中间加了个Kvo,来方便区别这个我们自己写的方法。

然后在NSObject+kvo.m里面来实现这个方法


到这里,我们的子类就已经创建好了

2、修改调用者isa指针其实只要一句话


3、重写set方法


这里我们可以拿到这个属性的新值,可是父类却不知道这个新值,这时我们通过msgSend来给父类发送消息,调用setName方法,并把新的name传过去

为了验证这里的代码是否正确,我在viewController里面调用一下,这里已经把原有的addObserver方法注释掉,调用了我们自己的addKvoObserver方法,结果显然是有效果的。

那么现在子类生成了,新值拿到了,isa指针也修改过了,set方法也重写了,只剩下要给外界发送通知了。

4、发送通知

首先我们要保存这个对象,方便在下面取到,然后我们在setName方法里取到这个observer之后,用msgSend调用方法来发送通知。

最后我们就可以在viewController里修改属性,并且获得通知了。


至此,我们的手写kvo就已经实现了。

第一次写文章,没有什么架构和排版,希望大家凑合看,提出各种问题。。。。

以后我会多多更新文章,方便大家互相学习技术,觉得好的话记得关注我哦!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,852评论 0 9
  • 本篇会对KVO的实现进行探究,不涉及太多KVO的使用方法,但是会有一些使用时的思考。 一、使用上的疑问 1.key...
    奋拓达阅读 551评论 0 2
  • 上半年有段时间做了一个项目,项目中聊天界面用到了音频播放,涉及到进度条,当时做android时候处理的不太好,由于...
    DaZenD阅读 3,051评论 0 26
  • 《招聘一个靠谱的 iOS》—参考答案(下) 说明:面试题来源是微博@我就叫Sunny怎么了的这篇博文:《招聘一个靠...
    YuWenHaiBo阅读 4,092评论 0 16
  • 30多年前,本书作者之一罗伯特·西奥迪尼出版了《影响力》一书,并结合当时的实证提出了六点普遍适用的说服原理。这些原...
    蕙茝_如常阅读 934评论 0 2