探索KVO的本质(一)

395 阅读3分钟

概述

KVO全称KeyValueObserving,是苹果提供的一套事件通知机制。允许对象监听另一个对象特定属性的改变,并在改变时接收到事件。由于KVO的实现机制,所以对属性才会发生作用,一般继承自NSObject的对象都默认支持KVO。

KVO和NSNotificationCenter都是iOS中观察者模式的一种实现。区别在于,相对于被观察者和观察者之间的关系,KVO是一对一的,而不一对多的。KVO对被监听对象无侵入性,不需要修改其内部代码即可实现监听。

KVO可以监听单个属性的变化,也可以监听集合对象的变化。通过KVC的mutableArrayValueForKey:等方法获得代理对象,当代理对象的内部对象发生改变时,会回调KVO监听的方法。集合对象包含NSArray和NSSet。

大家可能面试的时候经常遇到这样一个面试题:

iOS用什么方式实现对一个对象的KVO?(KVO的本质是什么?)

(如果你没有看我之前的博客,或者说对oc对象那些不了解的话,建议你先去看一下,就在前几天的博客****中,不然这篇文章有点费解)

知识回顾:

首先我们先来复习一下我们了解的kvo

这个就是比较常见的kvo的经典实现 我们知道,这个change的值跟你传入的option有一定关系,我们常见的一般就是传入NSKeyValueObservingOptionOld和NSKeyValueObservingOptionNew,一个新的值一个是老的值,所以change输出的时候会输出如上结果,而context是你监听的时候注入的值,在输出结果的时候,你传入的什么值,输出的也是什么值。

还有面试题会问:直接改变变量的值会触发kvo么?

答案:不会触发kvo

从上面的截图可以看出。self.person1调用setAge的时候才会触发-(void)observeValueForKeyPath...这个方法!此时应该细心的同学会有疑问:person1和person2都是调用setAge方法,代码都是一样,怎么会一个触发这个方法,一个没有触发呢?

kvo调用过程:

由于之前我们知道:没有进行kvo的,person2的isa是指向GDPerson的类对象,类对象中存储了isa、superclass、setage、age等等,所以person2就会通过isa指针找到GDPerson的类对象,再调用里面的setage方法,这是很清楚的

先看一个截图

截图可以看出

person1的类对象是NSKVONotifying_GDPerson,它是使用runtime动态创建的一个类

self.person1.isa =NSKVONotifying_GDPerson;

这里涉及到c语言的东西,有些代码是看不到,这里我直接说kvo它是调用了c语言的一个函数叫做 Foundation '_NSSetIntValueAndNotify',具体里面的代码是看不到,可以写一些伪代码如下:

主要是做了这么多事!

验证调用Foundation '_NSSetIntValueAndNotify'

我们可以用runtime的一个方法可以查看方法的具体实现 methodForSelector:<#(SEL)#>

接下来我将用代码证明:kvo派生类NSKVONotifying_GDPerson里面具体存在的类信息,继续来阐述这个kvo本质,并做一个总结。

如果觉得我写得对您有所帮助,请关注我,我会持续更新😄