在一个复杂的,有状态的系统中,当一个对象的状态发生改变,如何通知系统,并对状态改变做出相应的行为是必需考虑的一个问题,在iOS中为这类问题提供了4种解决方法:

1. NSNotifiactaion和NSNotificationCenter:通知中心 
2. Delegates:代理, 
3. Callback:回调, 
4. KVO(Key-Value Observing):键值观察

这篇文章就来说说通过KVO通知系统状态发生改变的用法。

KVO是什么? 
KVO是Object-C中定义的一个通知机制,其定义了一种对象间监控对方状态的改变,并做出反应的机制。对象可以为自己的属性注册观察者,当这个属性的值发生了改变,系统会对这些注册的观察者做出通知。其用途十分广泛,比方说,你的下载进度条是根据下载百分比决定的,那么,可以通过观察下载百分比的改变,刷新进度条的样式,来直观的反应下载进度等等。

KVO的用法 
根据上面的描述,一个KVO的用法主要就涉及3个部分:

1.为对象的属性注册观察者:对象通过调用下面这个方法为属性添加观察者

  1. - (void)addObserver:(NSObject *)observer
  2. forKeyPath:(NSString *)keyPath
  3. options:(NSKeyValueObservingOptions)options
  4. context:(void *)context
  • observer: 观察者对象. 其必须实现方法observeValueForKeyPath:ofObject:change:context:.
  • keyPath: 被观察的属性,其不能为nil.
  • options: 设定通知观察者时传递的属性值,是传改变前的呢,还是改变后的,具体的设定可以这儿:https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSKeyValueObserving_Protocol/Reference/Reference.html#//apple_ref/doc/c_ref/NSKeyValueObservingOptions,通常设置为NSKeyValueObservingOptionNew。
  • context: 一些其他的需要传递给观察者的上下文信息,通常设置为nil

2.观察者接收通知,并做出处理:观察者通过实现下面的方法,完成对属性改变的响应:

  1. - (void)observeValueForKeyPath:(NSString *)keyPath
  2. ofObject:(id)object
  3. change:(NSDictionary *)change
  4. context:(void *)context
  • keyPath: 被观察的属性,其不能为nil.
  • object: 被观察者的对象.
  • change: 属性值,根据上面提到的Options设置,给出对应的属性值
  • context: 上面传递的context对象。

3.清除观察者:对象通过下面这个方法移除观察者:

  1. - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath

4. 注意事项: 
使用KVO消息传递机制有两个要求:(1)观察者必须知道被观察对象,即在同一作用域。(2)观察者还需要知道被观察对象的生命周期,因为在销毁发送者对象之前,需要取消观察者的注册。 
另外:如果计划在Core Data对象上使用KVO,需要知道这跟一般的KVO使用方法有点不同。还必须结合Core Data的故障机制(faulting mechanism),一旦core data出现了故障,它将会触发其属性对应的观察者(即使这些属性值没有发生改变)。

5. 一些好的实践

  • (1)当一个观察者观察多个对象的相同属性(即不同Object,但是KeyPath相同),可通过设定静态的Context变量来区分不同的通知。
  • (2)使用NSStringFromSelector(@selector(method))来获取KeyPath,而不是直接通过NSString写属性名,这样编译器可以帮助发现属性名中的Typo。
  • (3)通过方法:+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key,通过一个Key观察多个属性值的改变。

吐槽 
这个API的设计真心的不好懂,另外把KeyPath设计为String也太什么了一点。

参考文章:http://beyondvincent.com/blog/2013/12/14/124-communication-patterns/ 
http://nshipster.com/key-value-observing/ 
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSKeyValueObserving_Protocol/Reference/Reference.html

iOS概念之KVO(Key-Value Observing)的更多相关文章

  1. KVO(Key Value Observing)

    *KVO能够监听某个对象属性的改变 原理:仅仅要给一个对象注冊一个监听,那么在执行时, 系统就会自己主动给该对象生成一个子类对象,而且重写自己主动生成的子类对象的被监听属性的set方法.然后在set方 ...

  2. iOS KVC 和 KVO 的学习

    KVC  (NSKey Value Coding) :键值编码 KVO (Key Value Observing) :键值监听 前言:我曾经用过 监听 一个音频何时结束 监听视频播放 状态等 用了这种 ...

  3. iOS KVC 和 KVO 区别简单总结

    KVC: key value coding,键值编码.是一种通过使用属性的名称(key)来间接访问对象属性的方法.这个方法可以不用通过 setter/getter 方法来访问对象的属性.该方法使用的实 ...

  4. iOS:KVC和KVO

    来源:  对月流 链接:http://www.jianshu.com/p/f1393d10109d 写在前面: 关于KVC和KVO各种博客多了去了,重新整理下,就当是温习一下吧,也还算是个新手,不对的 ...

  5. IOS开发-KVO

    一.什么是kvo? key-value observing,观察者模式 观察者,观察对象属性的变化,当被观察者该属性发生变化时,观察者会接收到通知,可以在回调函数中做相应的处理 二.有什么作用? 变化 ...

  6. iOS 错误:… is being deallocated while key value observing are still registered with it

    这个错误从字面上来看就是有一个实例由于被observing而无法被释放. 具体原因可能是该对象添加了一个oberver.所以释放的时候要先取消observer. 具体方法是在 dealloc 方法中: ...

  7. [iOS] KVC 和 KVO

    开发iOS经常会看见KVO和KVC这两个概念,特地了解了一下. 我的新博客wossoneri.com link KVC Key Value Coding KVC是一种用间接方式访问类的属性的机制.比如 ...

  8. iOS编程——Objective-C KVO/KVC机制[转]

    这两天在看和这个相关的的内容,全部推翻重写一个版本,这是公司内做技术分享的文档总结,对结构.条理做了更清晰的调整.先找了段代码,理解下,网上看到最多的一段的关于KVC的代码 先上代码 1.     1 ...

  9. iOS编程——Objective-C KVO/KVC机制

    来源:http://blog.sina.com.cn/s/blog_b0c59541010151s0.html 这两天在看和这个相关的的内容,全部推翻重写一个版本,这是公司内做技术分享的文档总结,对结 ...

随机推荐

  1. 【Android】Android如何实现手机震动

    实现手机震动其实很简单,手机震动使用是Vibrator类,然后震动也是需要权限的,在使用之前在AndroidManifest.xml文件中添加 <uses-permission android: ...

  2. 在iOS开发的Quartz2D使用中实现图片剪切和截屏功能

    原文  http://www.jb51.net/article/75671.htm 图片剪切一.使用Quartz2D完成图片剪切1.把图片显示在自定义的view中先把图片绘制到view上.按照原始大小 ...

  3. 你真的了解字典(Dictionary)吗? C# Memory Cache 踩坑记录 .net 泛型 结构化CSS设计思维 WinForm POST上传与后台接收 高效实用的.NET开源项目 .net 笔试面试总结(3) .net 笔试面试总结(2) 依赖注入 C# RSA 加密 C#与Java AES 加密解密

    你真的了解字典(Dictionary)吗?   从一道亲身经历的面试题说起 半年前,我参加我现在所在公司的面试,面试官给了一道题,说有一个Y形的链表,知道起始节点,找出交叉节点.为了便于描述,我把上面 ...

  4. SharePoint 中时间轴 Timeline的实现

    客户需要在OA中实现每日动态功能,能够记录每一位员工的每天的工作动态,我很快想到了时间轴,因为时间轴能很直观的现实员工每一刻的动态.就像Facebook的Timeline效果(点击查看). 尝试着搜索 ...

  5. linux中WDCP的日志彻底删除技巧

    apache或nginx都有开关默认日志,一个是正常访问日志,一个是错误的日志,目录在 /www/wdlinux/nginx-1.0.15/logs /www/wdlinux/httpd-2.2.22 ...

  6. 【转】UML类图符号 6种关系说明以及举例

    转自http://www.cnblogs.com/duanxz/archive/2012/06/13/2547801.html UML中描述对象和类之间相互关系的方式包括:依赖(Dependency) ...

  7. IntelliJ IDEA - 热部署插件JRebel ,对静态资源文件进行热部署?javascript、css、vm文件

    IntelliJ IDEA - 热部署插件JRebel ,对静态资源文件进行热部署?javascript.css.vm文件https://blog.csdn.net/feng_pump/article ...

  8. python执行selenium报错

    python + unittest + HTMLTestRunner 执行suite用例报错 Traceback (most recent call last): File "C:/ws/S ...

  9. The type org.apache.commons.cli.Options cannot be resolved. It is indirectly referenced from required .class files

    在搭建好Hadoop Eclipse开发环境后,编写map-reduce,遇到如下的问题: 从字面上可以看出,工程缺少org.apache.commons.cli.Options,这个包被间接的被其他 ...

  10. 怎么删除Elasticsearch里的index内容

    DELETE testindex 请求方式为 DELETE, 跟库名