问题: KVO的本质是什么?
问题: iOS是如何实现对一个对象的KVO?
当在iOS中对一个对象添加KVO时,实际上runtime会在原来的类基础上生成一个派生类 NSKVONotifying_xxx , 该类中重写了监听属性的set方法. 被监听的对象的isa指针会指向该派生类.
在Set方法中调用了Foundation框架中 _NSSetIntValueAndNotify 方法,内部实现主要有三方面
- 调用
willChangeValueForKey:
- 对属性进行赋值.
- 调用
didChangeValueForKey:
- 在 didChangeValueForKey 中会调用
oberserValueForKeyPath
@implementation NSKVONotifying_xxx
- (void)setName:(NSString *)name {
_NSSetIntValueAndNotify();
}
// 伪代码
void _NSSetIntValueAndNotify(NSString *name) {
[self willChangeValueForKey:@"name"];
_name = name;
[self didChangeValueForKey:@"name"];
}
// 伪代码
- (void)didChangeValueForKey:(NSString *)key {
[oberser oberserValueForKeyPath:key ofObject:self change:nil context:nil];
}
@end
当然了,除了上述方法,还有其他方法的做了一些修改.
@implementation NSKVONotifying_xxx
- (void)delloc {
// 做KVO的一些收尾工作
}
- (Class)class {
// 屏蔽KVO内部实现
return xxx;
}
- (BOOL)_isKVOA {
return YES;
}
@end
问题: 如何手动触发KVO?
直接手动顺序调用 willChangeValueForKey:
和 didChangeValueForKey
即可.
问题: 直接赋值成员变量(非属性)会不会触发KVO?
直接赋值成员变量不会触发KVO,KVO的本质可以认为是调用派生类的属性Set方法.
赋值成员变量不能触发Set方法,所以不能触发KVO.
Comments | 0 条评论