swift key-Value Observing

swift key-Value Observing

在swift中 只有继承 NSObject的类才具有 kvo特性
应用 kvo 的三个步骤

  1. 给属性添加 dynamic 修饰语
  2. 创建一个全局内容变量 用来标记观察者
  3. 加入到观察者中, 并在 deinit中 移除观察者

完整代码如下

import UIKit
//- [关于 kvo](https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html#//apple_ref/doc/uid/TP40014216-CH7-ID12)

class MyObjectToObsever: NSObject {
    // 要观察的属性 用 dynamic 修饰
    dynamic var myDate = NSDate()
    func updateDate(){
        myDate = NSDate()
    }
}

// 全局变量, 用来标记通知类型 也可以不标记
private var myContext = 0

class KVODemo: NSObject {
    var objectToObserver = MyObjectToObsever()
    
    override init() {
        super.init()
        // 把要观察的 属性加入观察中心
        objectToObserver.addObserver(self, forKeyPath: #keyPath(MyObjectToObsever.myDate), options: .new, context: &myContext)
    }
    
    //当被观察的属性 值 发生变化时 会走这个方法
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if context == &myContext {
            if  let newValue = change?[.newKey] {
                print("Date changed: \(newValue)")
            }
        }else{
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        }
    }
    
    //记得手动移除 观察者
    deinit {
        objectToObserver.removeObserver(self, forKeyPath: #keyPath(MyObjectToObsever.myDate))
    }
}

dynamic关键字

如果您有过OC的开发经验,那一定会对OC中@dynamic关键字比较熟悉,它告诉编译器不要为属性合成getter和setter方法。

Swift中也有dynamic关键字,它可以用于修饰变量或函数,它的意思也与OC完全不同。它告诉编译器使用动态分发而不是静态分发。OC区别于其他语言的一个特点在于它的动态性,任何方法调用实际上都是消息分发,而Swift则尽可能做到静态分发。

因此,标记为dynamic的变量/函数会隐式的加上@objc关键字,它会使用OC的runtime机制。

虽然静态分发在效率上可能更好,不过一些app分析统计的库需要依赖动态分发的特性,动态的添加一些统计代码,这一点在Swift的静态分发机制下很难完成。这种情况下,虽然使用dynamic关键字会牺牲因为使用静态分发而获得的一些性能优化,但也依然是值得的。

class Kraken {
    dynamic var imADynamicallyDispatchedString: String

    dynamic func imADynamicallyDispatchedFunction() {
        //Hooray for dynamic dispatch!
    }
}

使用动态分发,您可以更好的与OC中runtime的一些特性(如CoreData,KVC/KVO)进行交互,不过如果您不能确定变量或函数会被动态的修改、添加或使用了Method-Swizzle,那么就不应该使用dynamic关键字,否则有可能程序崩溃。

你可能感兴趣的:(swift key-Value Observing)