概述

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. Criteo电面二

    是第二次Video电面.本来约的是个俄罗斯人,结果面试时才发现换了一位国人大哥.面试这么久,还是第一次遇到国人,然后就被放水了,真给力! 第二天通知约onsite,查了地图,公司就在斯坦福对面.希望能 ...

  2. golang 中的指针

    # golang 中的指针 看了一篇[文章](http://blog.51cto.com/steed/2341409),写的很好.这里略微总结下重点: 1. 地址值.unsafe.Pointer.ui ...

  3. Direct3D 11 Tutorial 2: Rendering a Triangle_Direct3D 11 教程2:渲染一个三角形

    概要 在之前的教程中,我们建立了一个最小的Direct3D 11的应用程序,它用来在窗口上输出一个单一颜色.在本次教程中,我们将扩展这个应用程序,在屏幕上渲染出一个单一颜色的三角形.我们将通过设置数据 ...

  4. Vue .Net 前后端分离框架搭建

    [参考]IntellIJ IDEA 配置 Vue 支持 打开Vue项目 一.前端开发环境搭建 1.零基础 Vue 开发环境搭建 打开运行Vue项目 2.nodejs http-proxy-middle ...

  5. SSH配置struts校验发生No result defined for action actions.AdminLoginAction and result input

    配置struts校验发生No result defined for action actions.AdminLoginAction and result input,但是登录,success.jsp, ...

  6. Mock an function to modify partial return value by special arguments on Python

    Mock an function to modify partial return value by special arguments on Python python mock一个带参数的方法,修 ...

  7. [todo] 3rd

    十个 Laravel 5 程序优化技巧

  8. keras入门

    自己要搞深度学习,正好手上有本keras之父写的深度学习书,于是就从keras入手吧.看了一个电影的二分类问题,确实很简单,可以熟悉深度学习的流程.首先熟悉了结果keras的模块,如model,Seq ...

  9. linux的基本操作(RPM包或者安装源码包)

    RPM包或者安装源码包 在windows下安装一个软件很轻松,只要双击.exe的文件,安装提示连续“下一步”即可,然而linux系统下安装一个软件似乎并不那么轻松了,因为我们不是在图形界面下.所以你要 ...

  10. Eclipse使当前项目依赖另一个项目

    实例说明 在Eclipse中可以创建多个项目实现不同的软件开发,也可以使用多个项目来开发单独的大型软件,每个项目负责单独的模块部门,这样可以使软件的模块分类更清晰,可以单独的维护每个模块部分.但是项目 ...