kvo实现原理_透彻理解 KVO 观察者模式

172c1124ac31151ae333d3b484a8fa6c.png

前言

iOS开发中,有一种设计模式应用广泛,那就是观察者模式。苹果称其为 KVO(Key-Value Observing),既键值观察,总是有人把 KVC 和 KVO 混为一谈,实则它们只是名字长得像。相信看完本篇博客,并且看明白 github 中本人对其的代码实现,可以把 KVO 理解得更深刻。

KVO基于runtime实现代码 [1]

当然要实现它,我们就得先了解它,所以接下来会讲解 KVO 的用法以及简单原理。

一、KVO 用法

虽然用法很基础,还是简单提一下。

添加观察

[_obj addObserver:self forKeyPath:@"aName" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:(__bridge void *)(self)];

  1. 方法的调用者(就是这个_obj)就是被观察的对象。

  2. observer参数是回调的接收者。

  3. keyPath是一个寻找路径,最终落脚点是一个有效的可观察属性。

  4. options有几个配置回调可选项,NSKeyValueObservingOptionOld表示获取旧值,NSKeyValueObservingOptionNew表示获取新值,NSKeyValueObservingOptionInitial表示在添加观察的时候就立马响应一个回调,NSKeyValueObservingOptionPrior表示在被观察属性变化前后都回调一次。

  5. context是一个指针,用来准确匹配添加观察和接收观察,主要是在特定情况下无法区分该观察回调是否需要处理进行精确判断。

获取回调

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    
    if ((__bridge id)context == self) {
        NSLog(@"keyPath: %@, object: %@, change: %@, context: %@", keyPath, object, change, context);
    }
}

变换一个属性的值,打印如下:

keyPath: aName, object: , change: {
    
kind = 1;
new = jack;
old = "";
}, context: 

change字典里面的new和old就是我们需要的值了,kind是关键路径属性的类型标识,具体可以去看api。

移除观察

[_obj removeObserver:self forKeyPath:@"aName"];

移除观察很简单,和移除通知比较类似,我们需要在不用继续观察的时候移除它,比如在控制器的dealloc方法里面释放,值得注意的是重复移除会 crash。

KVO 设计的槽点

其实作为开发者,大家应该经常听到对 KVO 的吐槽:

  1. 回调方式单一。

  2. keypath设计容易写错。

  3. KVO 的回调有一个传递链,子类若不调用父类方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值