KVO提供一种机制,指定一个被观察对象(例如A类),当对象某个属性(例如A中的字符串name)发生更改时,对象会获得通知,并作出相应处理;【且不需要给被观察的对象添加任何额外代码,就能使用KVO机制】
在MVC设计架构下的项目,KVO机制很适合实现mode模型和view视图之间的通讯。
KVO 的实现依赖于 Objective-C 强大的 Runtime,其原理为:当观察某对象A时,KVO机制动态创建一个对象A当前类的子类,并为这个新的子类重写了被观察属性keyPath的setter 方法。setter 方法随后负责通知观察对象属性的改变状况。其实在底层 runtime是动态的添加了一个类
isa 指针的作用:每个对象都有isa 指针,指向该对象的类,它告诉 Runtime 系统这个对象的类是什么。
self.car = [[Car alloc]init];
/*
1.注册对象myKVO为被观察者:
option中,
NSKeyValueObservingOptionOld 以字典的形式提供 “初始对象数据”;
NSKeyValueObservingOptionNew 以字典的形式提供 “更新后新的数据”;
*/
[self.car addObserver:self forKeyPath:@"num" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
/* 2.只要object的keyPath属性发生变化,就会调用此回调方法,进行相应的处理:UI更新:*/
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
if([keyPath isEqualToString:@"num"] && object == self.car){
// 响应变化处理:UI更新(label文本改变)
self.label.text = [NSString stringWithFormat:@"当前的num值为:%@",[change valueForKey:@"new"]];
//上文注册时,枚举为2个,因此可以提取change字典中的新、旧值的这两个方法
NSLog(@"\n oldnum:%@-----newnum:%@",[change valueForKey:@"old"],[change valueForKey:@"new"]);
}
}
那么怎么证明KVO的底层是runtime呢?其实当我们用到runtime的时候底层会隐藏的给我们创建一个继承自我们要监听的这个类并且命名为 NSKVONotyfing_ 然后加要监听的类为名字的类
说起来有点绕口,这么说吧,用到我们这里就是一个叫NSKVONotyfing_Car的类,这里我已经创建好了,怎么证明呢,首先删除掉我创建的这个类,在observeValueForKeyPath这个方法打个断点运行,看控制台的输出即可