KVO底层原理

2021-09-13  本文已影响0人  风雨彩虹_123

KVO可以用于监听某个对象属性值得改变。

_NSSet*ValueAndNotify的内部实现:
调用willChangeValueForKey:
调用原来的setter实现
调用didChangeValueForKey:
在didChangeValueForKey:内部会调用observe的observeValueForKeyPath:ofObject:change:context:方法

KVO的本质是什么?
利用RuntimeAPI动态生成一个子类,并且让instance对象的isa指向这个全新的子类;
当修改instance对象的属性时,会调用Foundation的_NSSet*ValueAndNotify函数;

Runtime动态生成子类重写方法。

- (void)printMethodNamesOfClass:(Class)cls
{
    unsigned int count;
    // 获得方法数组
    Method *methodList = class_copyMethodList(cls, &count);
    
    // 存储方法名
    NSMutableArray *methodNames = [NSMutableArray array];
    
    // 遍历所有的方法
    for (int i = 0; i < count; i++) {
        // 获得方法
        Method method = methodList[i];
        // 获得方法名
        NSString *methodName = NSStringFromSelector(method_getName(method));
        // 拼接方法名
        [methodNames addObject:methodName];
    }
    // 释放
    free(methodList);
    
    // 打印方法名
    NSLog(@"%@ %@", cls, methodNames);
}

//注意:此处调用必须使用Runtime底层获取类对象的方法,因为Runtime自动生成
的类中重写了class方法,调用[self.person1 class]不能够获取到真正的类对象
[self printMethodNamesOfClass:object_getClass(self.person1)];

NSKVONotifying_MJPerson (
"setAge:",
class,
dealloc,
"_isKVOA"
)
setAge 方法 : KVO 实现的主要方法
class 方法:屏蔽内部实现,隐藏了Runtime自动生成子类的存在。
dealloc 方法 :当对象释放时,将Runtime生成的子类也进行释放。
_isKVOA 方法 : 说明自己是kvo类。

直接修改成员变量的值,是不会触发KVO的监听方法的。

上一篇下一篇

猜你喜欢

热点阅读