• 十一、无事勿扰,有事通知(2)——KVO


    概述

    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,实在是太麻烦了,这节咱们简单点,实现一个和上一节一样的程序。

     1 import UIKit
     2 
     3 class ViewController: UIViewController {
     4     @IBOutlet weak var passby1: UILabel!
     5     @IBOutlet weak var passby2: UILabel!
     6     @IBOutlet weak var passby3: UILabel!
     7     
     8     @objc dynamic var passerby1Say:String = ""
     9     @objc dynamic var passerby2Say:String = ""
    10     @objc dynamic var passerby3Say:String = ""
    11 
    12     override func viewDidLoad() {
    13         super.viewDidLoad()
    14         addObserver(self, forKeyPath: #keyPath(passerby1Say), options: [.new], context: nil)
    15         addObserver(self, forKeyPath: #keyPath(passerby2Say), options: [.new], context: nil)
    16         addObserver(self, forKeyPath: #keyPath(passerby3Say), options: [.new], context: nil)
    17     }
    18     
    19     override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    20         if keyPath == #keyPath(passerby1Say) {
    21             passby1.text = change![NSKeyValueChangeKey.newKey] as! String
    22         } else if keyPath == #keyPath(passerby2Say) {
    23             passby2.text = change![NSKeyValueChangeKey.newKey] as! String
    24         } else if keyPath == #keyPath(passerby3Say) {
    25             passby3.text = change![NSKeyValueChangeKey.newKey] as! String
    26         }
    27     }
    28 
    29     override func didReceiveMemoryWarning() {
    30         super.didReceiveMemoryWarning()
    31         // Dispose of any resources that can be recreated.
    32     }
    33     
    34     @IBAction func flyHeighAction(_ sender: UIButton) {
    35         passerby1Say = "路人甲:我不信"
    36         passerby2Say = "路人乙:我会信?"
    37         passerby3Say = "路人丙:差点信了"
    38     }
    39     
    40     deinit {
    41         removeObserver(self, forKeyPath: #keyPath(passerby1Say))
    42         removeObserver(self, forKeyPath: #keyPath(passerby2Say))
    43         removeObserver(self, forKeyPath: #keyPath(passerby3Say))
    44     }
    45 }
    View Code

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

    首先,我们确定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

    上一节           回目录          下一节 

  • 相关阅读:
    java中&和&&是怎么运算的
    struts中ActionForward 使用mapping.findForward如何传递get参数
    EL表达式_详解
    JSTL标签_详解
    inner join, left join, right join, full join 的区别
    CentOS7部署FastDFS+nginx模块
    一个实例明白AutoResetEvent和 ManulResetEvent的用法
    C#防止在画面上闪烁的Button
    C#中给Label控件设置BackgroundImage属性
    浅析C#异步操作
  • 原文地址:https://www.cnblogs.com/ansersion/p/9504760.html
Copyright © 2020-2023  润新知