05-iOS底层学习 | KVO(2)

57 阅读1分钟

大神链接

  • Person类
@interface Person : NSObject
{
    @public
    NSString *name; // 成员变量
}
@property(nonatomic,copy)NSString *nickName; // 属性

@end
NSLog(@"----开始----");
self.p = [[Person alloc] init];
// 创建监听
NSKeyValueObservingOptions options = NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew;
[self.p addObserver:self forKeyPath:@"nickName" options:options context:@"Person.nickName"];
[self.p addObserver:self forKeyPath:@"name" options:options context:@"Person.name"];
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    self.p.nickName = @"昵称";
    self.p->name = @"名字";
}

// 监听
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    NSLog(@"keyPath - %@",keyPath);
    NSLog(@"object - %@",object);
    NSLog(@"change - %@",change);
    NSLog(@"context - %@",context);
}

-(void)dealloc
{
    [self.p removeObserver:self forKeyPath:@"nickName"];
    [self.p removeObserver:self forKeyPath:@"name"];
}

通过上面打印成员变量没有触发监听,这是因为KVO是通过重写setter方法来监听的,成员变量并没有setter方法

小结: 1.对象在执行KVO的addObserver后,会动态生成一个NSKVONotifying_Class的子类,并且在子类添加setKey方法(重写了setter方法) 2.同时当前对象的isa指向NSKVONotifying_Class子类 3.NSKVONotifying_Class子类的setter方法增加willChangeValueForKey和didChangeValueForKey方法 4.执行完removeObserver方法并没有删除NSKVONotifying_Class子类,只是isa指针又重新指回当前类