美文网首页
Swift KVO自定义的属性需要注意

Swift KVO自定义的属性需要注意

作者: 落夏简叶 | 来源:发表于2020-04-20 11:01 被阅读0次

同事跟我说在控制器中不能KVO自定义的属性,我觉得奇怪,就实验了一下(结论当然是可以的,只是写法有问题需要注意,Swift和OC的写法不完全通用)。

demo1:
class ViewController: UIViewController {
    var name = "test"    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        addObserver(self, forKeyPath: "name", options: .new, context: nil)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        name = "shine"
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "name" {
            print("new value = \(change?[NSKeyValueChangeKey.newKey])")
        } 
    }
}

嗯,好像确实没调用观察的方法,没打印。那再试一下自定义一个类,在ViewController中观察类中的属性变化。

demo2:
//ViewController.swift
class ViewController: UIViewController {
    var name = "test"
    var personOne = Person()
      
    override func viewDidLoad() {
        super.viewDidLoad()
        
        addObserver(self, forKeyPath: "name", options: .new, context: nil)
        personOne.addObserver(self, forKeyPath: "age", options: .new, context: nil)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        personOne.age = 20
        name = "shine"
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "name" {
            print("new value = \(change?[NSKeyValueChangeKey.newKey])")
        } else if keyPath == "age" {
            print("new value = \(change?[NSKeyValueChangeKey.newKey])")
        }
    }
}

//Person.swift
 class Person: NSObject {
   var age = 0
}

结果当然是仍然没有打印,观察方法还是没调用。

结论:
  • 一番查找之后发现,观察的类需要加上@objcMembers关键字, 观察的属性需要加上dynamic关键字。
@objcMembers class Person: NSObject {
    dynamic var age = 0
}
  • 用以下的方法观察的类未加@objcMembers关键字,会直接崩溃(Swift 4后继承 NSObject 的 swift class 不再默认全部 bridge 到 OC)。这样会比较清晰的知道写法有问题。而上面的写法只是不调用,不会崩溃。

Fatal error: Could not extract a String from KeyPath Swift.ReferenceWritableKeyPath<testTwo.Person, Swift.Int>: file

personOne.observe(\Person.age, options: [.new,.old]) { (person, change) in
            print("new value = \(change.newValue)")
}
  • KVO 是一个纯 OC 的特性,只有NSObject 才能支持 KVO,所以观察的类要继承自NSObject。
  • 观察系统的UITableView的 contentSize,WKWebView的estimatedProgress等自带属性时是不需要注意这些的,系统应该默认实现了。

相关文章

  • Swift KVO自定义的属性需要注意

    同事跟我说在控制器中不能KVO自定义的属性,我觉得奇怪,就实验了一下(结论当然是可以的,只是写法有问题需要注意,S...

  • 自定义KVO,自动释放,监听多个属性

    自定义的 KVO,支持多属性监听,支持自动释放。 使用系统 KVO 监听属性 先来回顾下系统 KVO 是如何使用的...

  • 417,Swift 怎么实现KVO(面试点:基于NSObject

    一、KVO kvo键值观察者 Swift继承NSObject的KVO swift 实现kvo需要两个条件,第一要是...

  • Swift如何使用KVC/KVO

    // KVC/KVO// Swift支持KVC\KVO的条件// 属性所在的类、监听器最终继承自NSObject/...

  • RxSwift-KVO

    一、Swift-KVO 步骤一、添加观察 步骤二、观察回调 步骤三、移除观察 注意:监听的属性前 必须 加上 @o...

  • 初学swift之KVO

    初学swift之KVO KVO相当于给一个已有对象的属性添加一个属性观察器 KVO三步 1.注册 2.监听 3.移...

  • Swift的kvo

    Swift的kvo有两种方式第一种,直接用oc的kvo,但是需要注意的是1.class必须继承NSObject2....

  • KVO原理探究+自定义KVO实现

    概念 基本使用 触发模式 属性依赖 容器类的使用 自定义KVO 概念 KVO全称Key-Value Observi...

  • 自定义KVO的一些错误使用方式

    很多时候我们讲KVO,使用的时候需要注意移除监听,循环引用等问题,但是在自定义KVO的时候,却容易忽视几个问题。 ...

  • RxSwift:KVO监听对象属性

    在观察某个属性是否变化的时候,采用 KVO 的方式更为简单直接一些。 关于 Swift 的 KVO 使用方法,可以...

网友评论

      本文标题:Swift KVO自定义的属性需要注意

      本文链接:https://www.haomeiwen.com/subject/svzlihtx.html