KVO的实现原理

KVO的具体实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
/** p1 */
@property (strong, nonatomic) Person *p1;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 1.什么是通知
// 3个对象
self.p1 = [[Person alloc] init];
self.p1.name = @"p1";
// KVO是监听对象的属性值的改变的
[self.p1 addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
self.p1.name = @"123";
}
// 这个方法时属于 NSObject 类的,任何对象都可以作为观察者
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
NSLog(@"监听到了%@的%@属性发生了改变", object, keyPath);
NSLog(@"%@", change);
}
@end

KVO是基于运行时实现的

1
isa Class NSKVONotifying_Person 0x000001a12de2f545

上述例子中,当 p1.name 的值改变时,p1对象的 isa 指针会指向 NSKVONotifying_Person,意味着,在程序运行时,会动态生成一个 NSKVONotifying_Person 类,该类继承于 Person,而且该类中也有个 -setName: 方法,方法中在设置 name 的同时实现了:

1
2
3
4
5
6
7
8
- (void)setName:(NSString *)name
{
[super setName:name];
// 这两个方法底层会调用observer的- (void)observeValueForKeyPath: ofObject: change: context:这个方法
[self willChangeValueForKey:@"age"];
[self didChangeValueForKey:@"age"];
}