ObjC中KVO原理简析

栏目: Objective-C · 发布时间: 5年前

内容简介:通常我们通过显然实现这个功能的基础是属性值得改变,而属性值得改变需要调用setter方法。可是即使setter方法是我们重写的,并且在其实现中并没有编写关于监听属性改变通知监听的代码,KVO依然可以起作用。这是为什么呢?我们都知道一个类的实例方法存在于其类对象中,当一个类的实例向实例方法发送调用消息时候,会通过类实例的isa指针去其类对象中找到其对应的实例方法执行。setter方法就存在于类对象中。

通常我们通过 addObserver:forKeyPath:options:context 来监听某个实例的某个属性变化。当该属性的值发生变化的时候会通过 - (**void**)observeValueForKeyPath:(NSString *)keyPath ofObject:(**id**)object change:(NSDictionary<NSKeyValueChangeKey,**id**> *)change context:(**void** *)context 通知我们。

显然实现这个功能的基础是属性值得改变,而属性值得改变需要调用setter方法。可是即使setter方法是我们重写的,并且在其实现中并没有编写关于监听属性改变通知监听的代码,KVO依然可以起作用。这是为什么呢?

KVO实现原理

我们都知道一个类的实例方法存在于其类对象中,当一个类的实例向实例方法发送调用消息时候,会通过类实例的isa指针去其类对象中找到其对应的实例方法执行。setter方法就存在于类对象中。

新的类对象

我们通过runtime的 object_getClass() 直接利用实例对象的isa指针查找实例的类对象。

ObjC中KVO原理简析

这里之所以使用runtime获取类对象而不使用消息发送机制,是因为class是通过消息发送查找到class方法,在class方法中返回的类对象,而class方法可能被重写。

通过上图我们可以看出,使用KVO监听的属性的isa指向的类对象已经不是Person了,而是一个继承自Person的一个新的类 NSKVONotifying_Person ,我们并没有创建过这个类,它是objc的runtime动态生成的。

ObjC中KVO原理简析

NSKVONotifying_Person重写了父类的 setAge:classdealloc 方法,并且新增了一个 _isKVOA 方法。

NSKVONotifying_Person的setter方法

ObjC中KVO原理简析

我们可以看出在为person实例添加observer之前和之后的 setAge: 方法的实现发生了变化,之前是直接调用类对象中存储的实例方法,添加之后调用了Foundation框架中 _NSSetIntValueAndNotify 函数。

之所以是_NSSet*IntValue* AndNotify是因为age属性我们定义的是int类型,若是其他类型则会相应更改

_NSSetIntValueAndNotify 方法中,会调用 willChangeValueForKey ,然后调用父类的 setAge 方法,再调用 didChangeValueForKey 方法。在 didChangeValueForKey 中通知属性改变,从而使得 observeValueForKeyPath 得到消息。

NSKVONotifying_Person的class方法

在我们获取person实例的类对象的时候,我们发现使用runtime的 object_getClass 和使用消息发送机制 [_person class] 得到的结果不一样,这是因为NSKVONotifying_Person重写了class方法的实现,在实现中调用了 [super class] ,而NSKVONotifying_Person又是Person的子类,所以获取到的Person。

NSKVONotifying_Person的dealloc方法

由于runtime在实例对象添加了KVO之后动态创建了类和一些对象,所以可能会在dealloc中回收这些资源。

NSKVONotifying_Person的_isKVOA方法

_isKVOA 应该是会返回一个BOOL类型的值,表示是否使用了KVO。

手动触发KVO

ObjC中KVO原理简析

通过上面我们可以得知,KVO的实现主要是因为在setter方法中调用 _NSSetIntValueAndNotify ,而它调用 willChangeValueForKey ,然后调用父类的 setAge 方法,再调用 didChangeValueForKey 方法, didChangeValueForKey 告诉 observeValueForKeyPath 属性改变。所以我们可以通过实现will和did方法手动出发KVO。

成员变量会不会触发KVO

通过上面原理我们可以知道,KVO主要是通过重写setter方法实现的,而成员变量并不会实现setter方法,所以成员变量的改变并不会触发KVO。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数据挖掘技术

数据挖掘技术

[美]MichaelJ.A.B / 别荣芳、尹静、邓六爱 / 机械工业 / 2006-7 / 49.00元

本书是数据挖掘领域的经典著作,数年来畅销不衰。全书从技术和应用两个方面,全面、系统地介绍了数据挖掘的商业环境、数据挖掘技术及其在商业环境中的应用。自从1997年本书第1版出版以来,数据挖掘界发生了巨大的变化,其中的大部分核心算法仍然保持不变,但是算法嵌入的软件、应用算法的数据库以及用于解决的商业问题都有所演进。第2版展示如何利用基本的数据挖掘方法和技术,解决常见的商业问题。 本书涵盖核心的数......一起来看看 《数据挖掘技术》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具