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的监听方法的。
网友评论