iOS KVO原理的探究

释放双眼,带上耳机,听听看~!

使用KVO分三个步骤:

1 通过addObserver:forKeyPath:options:context:方法注册观察者,观察者可以接收keyPath属性的变化事件
Observer 被观察者对象   keyPath 需要观察的属性
options 参数
NSKeyValueObservingOptionNew 接收新值,默认为接收新值
NSKeyValueObservingOptionOld   接收旧值
NSKeyValueObservingOptionInitial 在注册时立即接收一次回调 在改变时也会发送通知
NSKeyValueObservingOptionPrior 改变之前发一次 改变之后发一次
Context  任意参数  可以用来标记 跟回调的context相对应
2 在观察者中实现observeValueForKeyPath:ofObject:change:context: 方法 当keyPath属性发生改变后,KVO回调这个方法来通知观察者。
change里面的kind
NSKeyValueChangeSetting   //set
NSKeyValueChangeInsertion //容器类 插入的
NSKeyValueChangeRemoval   //容器类 remove
NSKeyValueChangeReplacement //重新替换
3 当观察者不需要监听时,可以调用removeObserver:forKeyPath:方法将Kvo移除。 必须在观察者消失之前移除 否则会Crash

在调用addObserver方法后,KVO并不会对观察者进行强引用 所以要注意观察者的生命周期 否则会到这观察者被释放带来的Crash

KVO有两种触发模式 默认的是自动模式 下来我们说说手动模式

这个方法默认返回YES 返回yes时就是自动模式 返回NO时 就是手动模式  key 是要观察的属性 可以根据key进行动态调整
> 坑-> 不要全部返回NO 要根据key动态返回  不然? 瞬干爆炸 头皮发麻
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key;

当调整为手动模式的时候 改变被监听的对象的时候 是不会被监听到的(因为需要手动调用)

    [objc willChangeValueForKey:@"keyPath"];
objc.xxxx = xxx;(没有这句话的时候 观察者也会接收到回调)
[objc didChangeValueForKey:@"keyPath"];

KVO的属性依赖 关联关系

//关联关系
+ (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
NSString *objKey;
if ([key isEqualToString:objKey]) {
keyPaths = [[NSSet alloc]initWithObjects:@"需要关联key1",@"需要关联key1", nil];
}
return keyPaths;
}
这样关联了以后 被关联的值发生改变以后也会被key的观察者监听到

kvo如何观察容器类
容器类:数组 字典。。。

当你需要改变容器类的值得时候通过这种法获取容器 然后进行改值
NSMutableArray *array = [objc mutableArrayValueForKey:@"key"];
[ array addObjc:xx]
这个 array 和你之前的array已经不一样了 所以他会被监听到
其他的容器类同上 自己探究

KVO的底层原理 —>底层没有开元 一切源于网络

  1. 创建一个该对象的子类
  2. 重写set方法
  3. 修改外界的isa指针
[objc addObserver:self forKeyPath:@"page" options:NSKeyValueObservingOptionNew context:nil];
当调用这个方法之后 objc的isa指针不会再指向objc 而是指向 NSKVONotyfing_objc
系统在这个方法里创建了一个继承与objc 的子类并且在里面重写了 keyPath的set方法 当keyPath属性发生变化时 会回调到observeValueForKeyPath:ofObject:change:context: 方法里面

人已赞赏
iOS文章

IOS 之各种收起键盘

2020-4-30 0:31:50

iOS文章

iOS 修改导航栏透明度

2020-4-30 1:47:09

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索