KVO底层实现原理

KVO(Key-Value Observing)基于Objective-C的Runtime运行时机制,通过动态创建被观察对象的子类并重写setter方法来实现属性观察。KVO使用isa-swizzling,将被观察对象的isa指针指向新创建的NSKVONotifying_A类,使得setter调用触发通知机制。观察过程涉及willChangeValueForKey:和didChangeValueForKey:方法,确保在属性变更前后的通知。KVO的setter重写在运行时动态注入,保证了回调机制的执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

KVO 的实现依赖于 Objective-C  Runtime运行时机制 

基本的原理

当观察某对象A时,KVO机制动态创建一个对象A当前类的子类,并为这个新的子类重写了被观察属性keyPathsetter 方法。setter 方法随后负责通知观察对象属性的改变状况。

深入剖析

Apple 使用了 isa 混写(isa-swizzling)来实现 KVO 。当观察对象A时,KVO机制动态创建一个新的名为: NSKVONotifying_A的新类,该类继承自对象A的本类,且KVONSKVONotifying_A重写观察属性的setter 方法,setter 方法会负责在调用原 setter 方法之前和之后,通知所有观察对象属性值的更改情况。

(备注: isa 混写(isa-swizzlingisais a kind of  swizzling:混合)

NSKVONotifying_A类剖析:在这个过程,被观察对象的 isa 指针从指向原来的A类,被KVO机制修改为指向系统新创建的子类 NSKVONotifying_A类,来实现当前类属性值改变的监听

所以当我们从应用层面上看来,完全没有意识到有新的类出现,这是系统隐瞒了对KVO的底层实现过程,让我们误以为还是原来的类。但是此时如果我们创建一个新的名为“NSKVONotifying_A”的类(),就会发现系统运行到注册KVO的那段代码时程序就崩溃,因为系统在注册监听的时候动态创建了名为NSKVONotifying_A的中间类,并指向这个中间类了。

isa 指针的作用:每个对象都有isa 指针,指向该对象的类,它告诉 Runtime 系统这个对象的类是什么。所以对象注册为观察者时,isa指针指向新子类,那么这个被观察的对象就变成新子类的对象(或实例)了。 因而在该对象上对 setter 的调用就会调用已重写的 setter,从而激活键值通知机制。

这是KVO回调机制。内部神秘、外观简洁。

②子类setter方法剖析:KVO的键值观察通知依赖于 NSObject 的两个方法:willChangeValueForKey: didChangevlueForKey:,在存取数值的前后分别调用个方法:

被观察属性发生改变之前willChangeValueForKey:被调用,通知系统该 keyPath 的属性值即将变更;当改变发生后 didChangeValueForKey: 被调用,通知系统该 keyPath 的属性值已经变更;之后 observeValueForKey:ofObject:change:context: 也会被调用。且重写观察属性的setter 方法这种继承方式的注入是在运行时而不是编译时实现的。

KVO为子类的观察者属性重写调用存取方法的工作原理在代码中相当于:

-(void)setName:(NSString *)newName

{

    [self willChangeValueForKey:@"name"];    //KVO在调用存取方法之前总调用

    [super setValue:newName forKey:@"name"]; //调用父类的存取方法

    [self didChangeValueForKey:@"name"];     //KVO在调用存取方法之后总调用

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值