iOS KVO

KVO全称是Key-Value observing,即键值观察。提供了一种当其他对象属性被修改的时候能通知当前对象的机制。KVO很适合实现model和controller之间的通讯。

使用isa-swizzling来实现KVO。当观察对象A时,KVO机制动态创建一个名为:NSKVONotifying_A的新类,该类继承自对象A的本类,且KVO为NSKVONotifying_A重写观察属性的Setter方法,setter方法会负责在调用setter方法之前之后,通知所有观察对象属性值的更改情况。

在这个过程中,被观察对象的isa指针从指向原来的A类,被KVO机制修改为指向系统新创建的子类NSKVONotifying_A类,来实现当天类属性值改变的监听;当从应用层面看来,完全没有意识到有新的类出现,这是系统隐瞒了对KVO底层实现的过程,让我们误以为还是原来的类。但此时如果创建一个新的名为"NSKVONotifying_A"的类,就会发现系统运行到注册KVO的那段代码时程序就会崩溃,因为系统在注册监听的时候动态创建了名为NSKVONotifying_A的中间类,并指向这个中间类了。

子类setter方法剖析

KVO的键值观察通知依赖于NSObject的两个方法:willChangeValueForKey:和didChangeValueForKey:,在存取数值的前后分别调用2个方法:
被观察属性发生改变之前,willChangeValueForKey:被调用,通知系统该keyPath的属性值即将变化;
当改变发生后,didChangeValueForkey:被调用,通知系统该keyPath的属性值已经变更;
之后,observeValueForkey:ofOject:change:context:也会被调用。
重写观察属性的setter方法这种集成方式的注入是在运行时而不是在编译时实现的。

KVO为子类的观察者属性重写调用存取方法的工作原理在代码中相当于:

- (void)setName:(NSString *)name {
    [self willChangeValueForKey:@"name"]; // KVO在调用存取方法之前总调用
    [super setValue:name forKey:@"name"]; // 调用父类的存取方法
    [self didChangeValueForKey:@"name"]; // KVO 在低啊用存取方法之后总调用
}

你可能感兴趣的:(iOS KVO)