04从0搭建一个KVO

2021-08-23  本文已影响0人  白开了杯水
之前章节

01.OC实例对象的本质
02.OC有几种对象
03.对象的isasuperclass

网上很多文章讲解KVO的实现原理,但没过多久可能就忘了,这篇文章带你从苹果开发者的角度来实现KVO监听的技术,假设你现在是一名苹果开发人员,没错,我们现在就是一名苹果开发人员,遇到了一个问题,如下图


遇到了个问题

当age改变的时候,希望能调用personAgeChanged方法,这时我们会想要怎么去实现该功能呢?
最简单的,我们可以使用代理或通知模式来告诉外面,代理的话,假设有几个属性要监听的就要写很多个代理方法,太麻烦了,这里我们采用通知订阅者模式,那么通知模式通常有个通知管理中心,我们创建一个通知中心类,叫KZKVONotifictionCenter,KZ是个人前缀可忽略,如下图:


通知管理中心

分别有添加监听、移除监听、即将改变值、已经改变值方法,但如果我们要使用这个监听中心,其实也挺麻烦的,能否更加面向对象一点呢,这时我们就可以考虑使用oc的分类方法,同样创建一个NSObject+KVO分类,它的代码如下:


NSObject分类方法

有了分类方法,那么我们就可以这样子调用

分类添加监听的调用代码

哇,真的方便多了,那么我们的分类方法里面实现是怎样的呢?让我们来看看

分类添加通知的实现

大家可以看到,添加监听向监听中心添加,然后把自己的isa指向自己的子类KZKVONotifying_Person,为啥要指向自己的子类,我们先来看看子类KZKVONotifying_Person的代码

KZKVONotifying_Person子类代码

原来在子类中,重写了setAge,可以看到子类的setAge分别调用了kz_willChangeValueForKey和kz_didChangeValueForKey,这俩个方法,其实是让监听中心记录下改变前和改变后的值,存储起来,然后告知监听者

监听中心的实现

如果我们的监听者如果有实现kz_observeValueForKeyPath…这个方法,那么就可以监听到age改变时的通知了,如下图完整调用代码

完整调用

是不是很简单,这个模式主要是针对键值的监听,key-value-observer,那么我们就叫它KVO吧~

上面模拟了苹果对KVO的简单粗暴版实现,那么我们如何证明系统也是这样子实现的呢,首先证明的是调用addObserver这个方法后,isa指向改变的问题,可以看下图,指向前和指向后的isa

添加监听前isa的指向 添加监听后isa的指向

这里可能你会奇怪,KVONotifying_Person这个类没定义是从哪里来的,答案是苹果利用运行时,动态创建子类,继承了Person,这样子更加方便开发,神不知鬼不觉的实现了该技术,不用我们自己去创建子类实现。至于更换isa有啥用,我们在前面的章节讲过,isa指向了子类后,会去查找子类的方法列表,子类重写了对age的监听,这时调用了setAge,其实isa会去KVONotifying_Person调用setAge,如图

isa指向图
细节补充

本文部分知识来自李明杰的教程,感谢观看~

上一篇下一篇

猜你喜欢

热点阅读