基本原理
-
被观察者对象为A时,
KVO会为被观察者对象A, 动态创建当前类的子类,
并为这新创建的子类,重写KeyPath的setter方法。
setter
方法负责通知观察者,属性的改变状况。
深入解析
- Apple 使用了
isa
来实现 KVO 。 - 当被观察对象为A时,KVO机制动态创建一个新的名为:
NSKVONotifying_A
的新类,该类继承自对象A的本类。 - 且KVO为NSKVONotifying_A重写观察属性的
setter
方法 -
setter
方法会负责在调用原setter方法之前和之后,通知所有观察者属性值的更改情况。 -
NSKVONotifying_A
类剖析:
在KVO过程中, 被观察对象的isa指针从指向原来的A类,被KVO机制修改为指向系统新创建的子类NSKVONotifying_A
类, 来实现当前类属性值改变的监听;
示例 :
XMGWine
的真实类是被修改为,NSKVONotifying_XMGWine
。
NSKVONotifying_XMGWine
是系统创建的中间类。 - 为什么要有中间类,这样做的好处 ?
- 当对象注册为观察者时,
isa指针
指向被观察者的新子类,那么这个被观察的对象就神奇地变成新子类的对象或实例了。 - 因而在被观察者对象上对
setter
的调用就会调用已重写的setter
,从而激活键值通知机制。 - 从而来实现对"被观察者"的"类属性值"改变的监听 !
- 当对象注册为观察者时,
-
子类
setter
方法剖析:- KVO的键值观察依赖于
NSObject
的两个方法:willChangeValueForKey:
和didChangevlueForKey:
-
willChangeValueForKey:
被观察属性发生改变之前,调用此方法,通知系统该keyPath
即将改变。
- (void)willChangeValueForKey:(NSString *)key;
-
didChangevlueForKey:
被观察属性发生改变之后,调用此方法,通知系统该keyPath
的属性值已经变更。
- (void)didChangeValueForKey:(NSString *)key;
-
- 之后
observeValueForKey:ofObject:change:context:
方法被调用,且重写被观察者属性的setter方法,这种继承方式的注入是在运行时而不是编译时实现的。- KVO为子类"被观察者的属性",重写
setter
的工作原理在代码中相当于:
-(void)setName:(NSString *)newName{ [self willChangeValueForKey:@"name"]; -- KVO在调用存取方法之前总调用 -- 调用父类的存取方法 -- KVC, 给对应属性'name',赋予新值'newName'. [super setValue:newName forKey:@"name"]; [self didChangeValueForKey:@"name"]; -- KVO在调用存取方法之后总调用 }
-
注意:
- 只有遵循 KVO 变更属性值的方式,才会执行KVO的回调方法
- 如果赋值没有通过
setter
方法,而是直接修改属性对应的成员变量。
例如: 仅调用_name = @"newName"
,这时是不会触发KVO机制
- KVO为子类"被观察者的属性",重写
- KVO的键值观察依赖于
备注:
-
isa
: 混写(isa-swizzling
)
isa:is a kind of ; swizzling:混合,搅合; -
keyPath
: "被观察者"里面的属性。
需要监听其属性值变化的属性。
网友评论