3-KVO本质

1. 应用

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.tom = [[Person alloc] init];
    self.tom.age = 1;

    self.jack = [[Person alloc] init];
    self.jack.age = 2;
    //添加监听
    [self.tom addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    //查找setAge方法地址
    NSLog(@"tom - %p", [self.tom methodForSelector:@selector(setAge:)]);
    NSLog(@"jack - %p", [self.jack methodForSelector:@selector(setAge:)]);
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    NSLog(@"%@-%@-%@",object,keyPath,change);
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    self.tom.age ++;
    //手动触发监听方法
    [self.tom willChangeValueForKey:@"age"];
    [self.tom didChangeValueForKey:@"age"];
}


- (void)dealloc {
    //移除监听
    [self.tom removeObserver:self forKeyPath:@"age"];
}

2. 本质

当未给对象添加监听时,对象的isa指针指向它的类对象


image.png

当给对象添加监听时,对象的isa指针指向类对象NSKVONotifying_Person,NSKVONotifying_Person类为Person类的子类,此类为runtime动态生成


image.png

NSKVONotifying_Person类中的setAge方法和Person中的setAge方法


3-KVO本质_第1张图片
image.png

3. 获取类对象的方法

- (void)printMethodForClass:(Class)cls{
    unsigned int count;
    
    Method* methodList =  class_copyMethodList(cls, &count);
    
    for (int i = 0; i < count; i++) {
        Method itemMothod = methodList[I];
        
        NSString* methodName = NSStringFromSelector(method_getName(itemMothod));
        NSLog(@"%@",methodName);
    }
    //释放
    free(methodList);
}
[self printMethodForClass:object_getClass(self.tom)];
3-KVO本质_第2张图片
image.png

你可能感兴趣的:(3-KVO本质)