关于KVO

介绍

允许对象监听另一个对象特定属性的改变
KVO 一对一
NSNotificationCenter 一对多
KVO可以监听单个属性的变化,也可以监听集合对象的变化
KVCmutableArrayValueForKey: 获得代理对象, 代理对象的内部对象发生改变时,会调用KVO监听的方法.(NSArray, NSSet)

流程

  1. 注册方法
    addObserver: forKeyPath: options: context:
    
    options: NSKeyValueObservingOptionNew
    NSKeyValueObservingOptionOld
    NSKeyValueObservingOptionInitial 注册观察者后,立即调用一次
    context: 传值
    addObserver: 不会强引用, 所以要注意
  2. 监听方法
    observeValueForKeyPath: ofObject: change: context:
    
    不实现会crash
    change存放KVO属性相关的值
    change中还有NSKeyValueChangeKindKey字段, 和NSKeyValueChangeOldKey平级关系,来提供本次更改的信息,对应NSKeyValueChange的value.
    若被观察者为集合, NSKeyValueChangeKindKey中会包含NSKeyValueChangeInsertion, NSKeyValueChangeRemoval, NSKeyValueChangeReplacement的信息
  3. 移除方法
    removeObserver: forKeyPath: 
    
    需要在观察者消失之前,否则会crash

兼容的调用方式

点语法和set语法

[object setName:@""];
[object setValue:@"" forKey:@"name"];
[document setValue:@"" forKeyPath:@"object.name"];
Object *obj = [[Object alloc] init];
//获取代理集合
NSMutableArray *arrayM = [object mutableArrayValueForKey:@"name"];
[arrayM addObject:obj];

实际应用

KVOmodelcontroller之间进行通信

注意点

KVO中的addObserverremoveObserver成对
initadd,在deallocremove

手动调用KVO

willChangeValueForKey:
didChangeValueForKey:
手动调用这两个方法
控制当前对象自动调用过程,可以重写

+ (BOOL)automaticallyNotifiesObserverForKey:(NSString *)theKey;

实现原理

isa-swizzling
在运行时根据原来创建一个中间类,这个中间类为原类的子类,动态修改当前对象的isa指向中间类,并将class方法重写,返回原来类的Class
NSKVONotifying_xxx 命名中间类

缺点

使用不当容易crash: addremove observer被释放 keyPath传错
keyPath是字符串,修改属性不报错,可以使用NSStringFromSelector(@selector(isFinished)).
KVO不支持block,可以使用Facebook开源的KVOController, 本质是对系统KVO的封装,兼容blockaction

猜你喜欢

转载自blog.csdn.net/weixin_42983482/article/details/83626285
KVO