🚩 KVO是利用runtime的特性动态生成观察对象的子类,然后重写被观察对象的属性的set方法
可用于监听某个对象属性值的改变
1 对Person
对象的age
属性建立监听
// 如何设置属性的KVO
@property (nonatomic, strong) Person *person1;
- (void)viewDidLoad {
[super viewDidLoad];
_person1 = [[Person alloc] init];
_person1.age = 32;
// 需要返回的数据,新的值 | 旧的值
NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
// 对person1属性age设置监听,附带信息:@"附加信息"
[self.person1 addObserver:self forKeyPath:@"age" options:options context:@"附加信息"];
}
2 实现监听方法,当age
被设置时,该方法将被掉用
// person1.age改变时会调用这里
-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary<NSKeyValueChangeKey,id> *)change
context:(void *)context {
NSLog(@"keyPath: %@, object: %@;\nchange: %@, context: %@", keyPath, object, change, context);
}
3 最后,当不需要监听时,适时移除监听
// 监听者销毁时移除相应的监听
-(void)dealloc {
[_person1 removeObserver:self forKeyPath:@"age"];
}
KVO的本质(内部实现)
打印对象isa地址、name类名
在设置监听前后打印person1
,2的isa
地址。发现person1
在设置完监听后地址发生了改变;在设置监听前后打印person1
,2的类名。发现person1在设置完监听后改变为:NSKVONotifying_Person
小结
可以看出,程序在runtime的时候动态生成了 NSKVONotifying_Person
,NSKVONotifying_Person
继承于 Person
,当改变 age
的值时,即调用 setAge:
方法。NSKVONotifying_Person
重写了 setAge:
并做了其他事情。具体做了那些事可以猜测:
didChangeValueForKey:
内部会调用observer的observeValueForKeyPath:ofObject:change:context:
方法
KVO是利用runtime的特性动态生成观察对象类的子类,然后重写被观察对象的属性的set方法。
如何手动触发KVO?
手动调用willChangeValueForKey:
和didChangeValueForKey:
。只调用didChangeValueForKey:
是无法触发的。