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

来源:互联网 发布:淘宝清洗订单会降权吗 编辑:程序博客网 时间:2024/06/05 02:32

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
原创粉丝点击