我们都知道苹果的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就已经实现了。
第一次写文章,没有什么架构和排版,希望大家凑合看,提出各种问题。。。。
以后我会多多更新文章,方便大家互相学习技术,觉得好的话记得关注我哦!!!
网友评论