问题: KVO的本质是什么?

问题: iOS是如何实现对一个对象的KVO?


当在iOS中对一个对象添加KVO时,实际上runtime会在原来的类基础上生成一个派生类 NSKVONotifying_xxx , 该类中重写了监听属性的set方法. 被监听的对象的isa指针会指向该派生类.

在Set方法中调用了Foundation框架中 _NSSetIntValueAndNotify 方法,内部实现主要有三方面

  1. 调用 willChangeValueForKey:
  2. 对属性进行赋值.
  3. 调用 didChangeValueForKey:
  4. 在 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.


IT界无底坑洞栋主 欢迎加Q骚扰:676758285