KVO

KVO全称为Key-Value Observing, 即键值监听,用于指定对象属性值的改变。

定义如下一个Person类:

1
2
3
@interface Person : NSObject
@property (assign, nonatomic) int age;
@end

给Person类的instance对象添加KVO:

1
2
3
// 给person1对象添加KVO监听
NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
[self.person addObserver:self forKeyPath:@"age" options:options context:nil];

当给Person的instance对象添加KVO监听后,Runtime会动态创建一个名为NSKVONotifying_Person的Person子类,并将instance对象的isa指针指向这个子类Class。

NSKVONotifying_Person类的setAge:方法的伪代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (void)setAge:(int)age
{
//调用Foundation框架的_NSSet***ValueAndNotify方法,与具体参数类型有关
_NSSetIntValueAndNotify();
}

void _NSSetIntValueAndNotify()
{
[self willChangeValueForKey:@"age"];
[super setAge:age];
[self didChangeValueForKey:@"age"];
}

- (void)didChangeValueForKey:(NSString *)key
{
// 通知监听器,属性值发生了改变
[oberser observeValueForKeyPath:key ofObject:self change:nil context:nil];
}

其他方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 屏蔽内部实现,隐藏了NSKVONotifying_Person类的存在
- (Class)class
{
return [Person class];
}

- (void)dealloc
{
// 收尾工作
}

- (BOOL)_isKVOA
{
return YES;
}

由此可见,直接修改成员变量的值不会触发KVO。