在一个复杂的,有状态的系统中,当一个对象的状态发生改变,如何通知系统,并对状态改变做出相应的行为是必需考虑的一个问题,在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. 【Smali】Smali文件的动态调试

    1.简介 smalidea是一个IntelliJ IDEA/Android Studio smali语言插件,可实现动态调试smali代码.下载地址为:https://github.com/Jesus ...

  2. 【Oracle】详解Oracle中的序列

    序列: 是oacle提供的用于产生一系列唯一数字的数据库对象. 自动提供唯一的数值 共享对象 主要用于提供主键值 将序列值装入内存可以提高访问效率 创建序列: 1.  要有创建序列的权限 create ...

  3. 【Oracle】详解Oracle中NLS_LANG变量的使用

    目录结构: contents structure [+] 关于NLS_LANG参数 NSL_LANG常用的值 在MS-DOS模式和Batch模式中设置NLS_LANG 注册表中NLS_LANG和系统环 ...

  4. 中小研发团队架构实践之生产环境诊断工具WinDbg 三分钟学会.NET微服务之Polly 使用.Net Core+IView+Vue集成上传图片功能 Fiddler原理~知多少? ABP框架(asp.net core 2.X+Vue)模板项目学习之路(一) C#程序中设置全局代理(Global Proxy) WCF 4.0 使用说明 如何在IIS上发布,并能正常访问

    中小研发团队架构实践之生产环境诊断工具WinDbg 生产环境偶尔会出现一些异常问题,WinDbg或GDB是解决此类问题的利器.调试工具WinDbg如同医生的听诊器,是系统生病时做问题诊断的逆向分析工具 ...

  5. C语言中的 (void*)0 与 (void)0

    前几天看到一个宏, 它大概是这样的: #define assert_param(expr) ((expr) ? (void)0 : assert_failed((u8 *)__FILE__, __LI ...

  6. C++模板”>>”编译问题与词法消歧设计

    在编译理论中,通常将编译过程抽象为5个主要阶段:词法分析(Lexical Analysis),语法分析(Parsing),语义分析(Semantic Analysis),优化(Optimization ...

  7. Inside i++

    i++.++i.i=i+1.效率怎么样?看过一本书上说,i++比i=i+1好的地方是因为i=i+1中的那个1要占用一个寄存器,所以速度没有i++快,于是我想验证一下.另外,以前听说过Java中的“i= ...

  8. Sails入门指南

    1.全局观:sails理念,框架结构 2.试用sails的scaffolding工具,创建model,创建controller, 3.启动server,试用blueprint, 4.进阶: 4.0 数 ...

  9. github 仓库共享上传权限

    https://blog.csdn.net/qq_33210042/article/details/79717497 打开仓库 -> Settings -> Collaborators 然 ...

  10. 在java项目中使用 Lombok 及可能问题

    一.Maven项目使用步骤一般包含两步,1)引入依赖 2)特定的 IDE 引入对应的插件 1)在POM中引入依赖 <!-- https://mvnrepository.com/artifact/ ...