概述

Key-Value-Observe,简称KVO,和上节介绍的Notification师出同门,主要目的都是为了实现观察者模式。

虽说是同门师兄弟,但是各自精通的技艺却是各不相同的。

不像Notification,KVO没有所谓“Center”的角色,观察者和被观察者之间是直接交互的,没有第三者插脚。这个特点带来的最直接的好处就是,KVO比Notification更加的简单易用。阴阳相随,利弊相从。正因为KVO没有“Center”约束,所以当参与观察和被观察的角色增多的时候,KVO管理起来就会显得力不从心了,而且当有大量事件并发执行的时候,NotificationCenter还有整合优化以提高性能的作用,而KVO则没有这方面的内容(出处)。

最后需要注意的一点是,KVO是相伴NSObject的产物,NSObject是Object-C的基类,在swift中,并非所有的类都继承了NSObject,这也就意味着并非所有的类都能用KVO。然而,这些倒并不构成我们使用KVO的顾虑,毕竟大部分常用的类都是继承NSOject的,我们大可放心使用KVO,尤其在观察对象单个属性变化方面,KVO绝对是个不可多得的好帮手。

单点,码代码的方式简单点

在上一节Notification中,我们又是要创建NotificationCenter又是要重写UILabel,实在是太麻烦了,这节咱们简单点,实现一个和上一节一样的程序。

 import UIKit

 class ViewController: UIViewController {
@IBOutlet weak var passby1: UILabel!
@IBOutlet weak var passby2: UILabel!
@IBOutlet weak var passby3: UILabel! @objc dynamic var passerby1Say:String = ""
@objc dynamic var passerby2Say:String = ""
@objc dynamic var passerby3Say:String = "" override func viewDidLoad() {
super.viewDidLoad()
addObserver(self, forKeyPath: #keyPath(passerby1Say), options: [.new], context: nil)
addObserver(self, forKeyPath: #keyPath(passerby2Say), options: [.new], context: nil)
addObserver(self, forKeyPath: #keyPath(passerby3Say), options: [.new], context: nil)
} override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == #keyPath(passerby1Say) {
passby1.text = change![NSKeyValueChangeKey.newKey] as! String
} else if keyPath == #keyPath(passerby2Say) {
passby2.text = change![NSKeyValueChangeKey.newKey] as! String
} else if keyPath == #keyPath(passerby3Say) {
passby3.text = change![NSKeyValueChangeKey.newKey] as! String
}
} override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
} @IBAction func flyHeighAction(_ sender: UIButton) {
passerby1Say = "路人甲:我不信"
passerby2Say = "路人乙:我会信?"
passerby3Say = "路人丙:差点信了"
} deinit {
removeObserver(self, forKeyPath: #keyPath(passerby1Say))
removeObserver(self, forKeyPath: #keyPath(passerby2Say))
removeObserver(self, forKeyPath: #keyPath(passerby3Say))
}
}

这下够简单了吧,代码部分总过不超过五十行,运行结果和上一节是一样儿一样儿的(效果图)。现在我们来简单分析一下。

首先,我们确定UIViewController是继承自NSObject的,所以我们可以调用“addObserver”函数和重写“observeValue”函数。

然后我们把需要观察的属性用addObserver纳入观察范围。

addObserver函数的作用是:调用addObserver函数的对象将一个NSObject的属性纳入观察范围。

此处调用addObserver的是ViewController,所以ViewController是观察者。

addObserver的第1个参数是被观察者,此处为self,所以ViewController又是被观察的对象。

addObserver的第2个参数是被观察者的属性,此处为passerby1Say/passerby2Say/passerby3Say。passerby1Say/passerby2Say/passerby3Say必须由dynamic关键字修饰,表示支持动态观察,@objc是修饰语句“#keyPath”要求的,用于编译阶段检查错误。

addObserver的第3个参数是1个列表,表示触发观察事件属性,“.new”表示所观察的属性改变时,将新值作为参数传递给观察者;“.old”表示所观察的属性改变时,将旧值作为参数传递给观察者。

addObserver的第4个参数表示观察事件触发时所传递的参数,一般很少用到,此处置为nil。

既然我们已经将所要关注的属性都纳入观察范围了,那么现在我们只要关注观察事件发生时的情形就可以了。

观察者通过“obsserveValue”函数接收观察事件,其中参数change是1个字典,它包含了属性改变前的旧值或改变后的新值,依据之前调用addObserver时的参数options而定,其他代码是不言自明的,此处不再赘述。

源码下载:https://pan.baidu.com/s/1TosFFebbSuo6qlKVRuZtxg

上一节           回目录          下一节

十一、无事勿扰,有事通知(2)——KVO的更多相关文章

  1. 十、无事勿扰,有事通知(1)——NSNotification

    概述 很久很久以前,有一只菜鸟正在美滋滋的撸着他的嵌入式C代码.然而有一天,老板对菜鸟说:“别撸C了,从现在开始你就写swift开发ios了.”菜鸟一脸懵逼,但还是照做了. 又有一天,菜蛋谄媚的对菜鸟 ...

  2. OC 观察者模式(通知中心,KVO)

    OC 观察者模式(通知中心,KVO) 什么是观察者模式??? A对B的变化感兴趣,就注册为B的观察者,当B发生变化时通知A,告知B发生了变化.这就是观察者模式. 观察者模式定义了一种一对多的依赖关系, ...

  3. iOS开发——高级篇——iOS中如何选择delegate、通知、KVO(以及三者的区别)

      在开发IOS应用的时候,我们会经常遇到一个常见的问题:在不过分耦合的前提下,controllers[B]怎么进行通信.在IOS应用不断的出现三种模式来实现这种通信:1委托delegation2通知 ...

  4. iOS中如何选择delegate、通知、KVO(以及三者的区别)

    转载自:http://blog.csdn.net/dqjyong/article/details/7685933 在开发IOS应用的时候,我们会经常遇到一个常见的问题:在不过分耦合的前提下,contr ...

  5. 代理、通知、KVO的应用

    实现下图效果,每点击一次cell的“加号”或者“减号”,就可以让“底部view”的总价进行对应的增加或者减少. 下图是实际运行效果图: 图(1) 因为“底部UIView”需要一直显示在底部.如果把底部 ...

  6. iOS 之单例,代理,通知,KVO,Block全能解析

    //单例 //.h + (Instannce *)shareInstance; //.m static Instannce *instance = nil; @implementation Insta ...

  7. 代理丶通知丶KVO之间区别和各自优势

    文/OyeOnoOmg(简书作者)原文链接:http://www.jianshu.com/p/75d3fd218a23著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 今天在网上看到一个 ...

  8. 61 (OC)* 代理 block 通知 代理 kvo

    1.从源头上理解和区别block和delegate delegate运行成本低,block的运行成本高. block出栈需要将使用的数据从栈内存拷贝到堆内存,当然对象的话就是加计数,使用完或者bloc ...

  9. cocos2d-x游戏引擎核心之十一——并发编程(消息通知中心)

    [续] cocos2d-x游戏引擎核心之八——多线程 这里介绍cocos2d-x的一种消息/数据传递方式,内置的观察者模式,也称消息通知中心,CCNotificationCenter. 虽然引擎没有为 ...

随机推荐

  1. sqoop导入数据到hive中元数据问题

    简单配置了sqoop之后开始使用,之前用的时候很好用,也不记得有没有启动hivemetastore,今天用的时候没有启动,结果导入数据时,如果使用了db.tablename,就会出现找不到数据库的错, ...

  2. ant 通配符

    ant 通配符 我们常用的匹配模式有ANT模式,比如acegi可以用PATTERN_TYPE_APACHE_ANT来使用ANT匹配模式,那什么是ANT匹配模式呢.   ANT通配符有三种:     通 ...

  3. HTTP 06 用户认证

    SSL 客户端认证具有高度的安全等级, 但是因为导入及维持费用等问题, 还未普及. 认证的方式有很多种, 多半是 基于表单的认证(即用户名/密码的方式) Session 管理及 Cookie 应用 基 ...

  4. [Z] C#程序中设置全局代理(Global Proxy)

    https://www.cnblogs.com/Javi/p/7274268.html 1. HttpWebRequest类的Proxy属性,只要设置了该属性就能够使用代理了,如下: 1        ...

  5. C++笔试面试题整理

    朋友给出的一些常见的C++面试题,特整理如下,后期遇到新的再更新. 面试题 列举并解释C++中的四种运算符转化,说明它们的不同点: static_cast: 在功能上基本上与C风格的类型转换一样强大, ...

  6. 6 个开源的家庭自己主动化工具 | Linux 中国

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/F8qG7f9YD02Pe/article/details/79466841 wx_fmt=jpeg& ...

  7. 蜕变成蝶~Linux设备驱动中的并发控制

    并发和竞争发生在两类体系中: 对称多处理器(SMP)的多个CPU 内核可抢占的单CPU系统 访问共享资源的代码区域称为临界区(critical sections),临界区需要以某种互斥机制加以保护.在 ...

  8. ABBYY PDF Transformer+功能概述

    ABBYY PDF Transformer+是一个新的.全面的巧妙解决PDF文档的工具,它将泰比的光学字符识别(OCR)技术和Adobe®PDF技术完美结合,以确保实现便捷地处理任何类型的PDF文件, ...

  9. ES6 扩展运算符 三点(...)

    含义 扩展运算符( spread )是三个点(...).它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列. console.log(...[, , ]) // 1 2 3 conso ...

  10. 如何在spring-boot web项目中启用swagger

    swagger的三个项目及其作用 我们打开swagger的官网,会发现有三个swagger相关的项目,它们分别是 swagger-editor 作用是通过写代码,生成文档描述(一个json文件或其他格 ...