爬爬爬之路:UI(十五) KVO

KVO的简单介绍

KVO概念

KVO:(Key-Value-Observer)键值观察者,是观察者设计模式的⼀种具体实现。
KVO触发机制:⼀个对象(观察者),监测另⼀对象(被观察者)的某属性是否发⽣变化,若被监测的属性发⽣的更改,会触发观察者的⼀个⽅法(⽅法名固定,类似代理⽅法)

KVO使⽤步骤:

  1. 注册观察者(为被观察者指定观察者以及被观察属性)
  2. 实现回调⽅法
  3. 触发回调⽅法(被观察属性发⽣更改)
  4. 移除观察者

KVO的优势

简单而言, KVO就是可以对某一个属性进行监测. 当这个值发生变化的时候, 可以即时的自动的做出响应. 通常我们在改变一个值的时候, 如果有另外一个对象需要依据它发生改变(比如更改状态), 若不用KVO的时候, 我们只能选择在该值变化后, 手动的调用或者书写更改状态的代码. 如果一时疏忽忘记了, 就有可能导致状态不对.

还有一些情况是由于值的变化是在子线程中修改的, 这时候你可能无法准确的判断什么时候修改完成, 但是又需要根据子线程完成后的值对主线程中的某个状态进行修改, 就可以使用KVO来完成, 省心不少.

利用KVO来检测值的变化来修改值, 不需要我们费心费代码的去就人工检测. 只需要交给系统即可.


KVO的实现

KVO功能强大, 但是代码却十分简单.

让被观测者对象添加一个监听者对象, 监听自己的某个值用到的方法如下:

- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
// 这是NSObject中的一个方法, 所以所有对象均可调用本方法, 让另一个对象来监听自己的某个属性的变化.

/* 
使用介绍:
调用本方法的对象是被检测对象 (MVC模式中, 通常都是Model层对象调用本方法)
第一个参数是监听对象(由于本方法通常是在Controller层中实现, 所以此处通常都是写self) 
第二个参数是被监听的属性的属性名(比如要监听的是Model类中的name属性, 此处就写@"name")
第三个参数是监听的监听的事件(通常都是监测属性值的变化, 写法为 
NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
最后一个参数是当监听到了事件的触发后, 携带给监听调用方法的参数, 可以是任意的参数(但必须是对象类型的参数), 比如可以携带一个字符串, 一个数组, 一个NSIndexPath等等, 根据场景自行决定需要携带的参数.
*/

当被监听的对象的属性发生了预期中的事件是, 触发的方法如下:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;

/*
本方法是需要在监听者的类中重写的.

重写的内容就是我们被监听的值发生变化后的相应操作.

第一个参数是被监听的属性
第二个参数是被监听的对象
第三个参数是存放了变化后前后的值 变化前的值是 键名为@"old"对应的值 变化后的值是 键名为@"new"对应的值
第四个参数就是添加监听事件时候携带的参数.


注意, 一个类中只能重写一次本方法, 无论添加了多少个监听事件, 都是触发本方法. 若是每个监听事件的处理方法不一样, 可以利用keyPath或者object的不同, 用if来判断即可.
*/


// 若是只需要监听者响应一次监听事件, 也就是只需要本方法执行一遍就不要再执行了. 需要移除该监听事件
// 移除方法是在本处添加语句如下
[object removeObserver:self forKeyPath:keyPath];

/*
也可以根据keyPath和object两个参数的值来判断需要移除的是哪一个监听事件
*/

最后给一个小提示, KVO在时间线上是在添加后才生效, 若是值的变化在KVO添加之前就已经发生了. 那么KVO就无效了, KVO只会在监听事件添加了之后, 响应被检测属性的值的变化.

主要场景就是主线程和子线程的共同存在时, 由于子线程和主线程并发进行, 通常子线程的时间会慢于主线程运行的时间.
所以:

  1. 当值的变化和KVO都是在主线程或者子线程中, 那么KVO需要在值变化之前添加才能检测到.
  2. 当KVO是在主线程中添加, 而值的变化是在子线程中, 那么KVO语句写在调用子线程改变值的语句之后也是可以的.
  3. 若果KVO是在子线程中添加, 但值的变化是在主线程中, 那么无论KVO所在的子线程调用语句是否在值变化的前后后不会被响应.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值