Swift 4新知:KVC和KVO新姿式

隨着 keypath 獲得加強,KVC 和 KVO 的 API 都有了一些進化。html

struct 也支持 KVC

一個感人的進步就是 struct 也支持 KVC 了。可是並非使用原有的setValue:forKeypath的api。而是利用了swfit 4增長的一個語法特性:自定義索引能夠有參數名。
直接上代碼吧:ios

struct ValueType {
    var name:String
}

var object = ValueType(name: "zhuo")
let name = \ValueType.name

// set
object[keyPath: name] = "swift4"
// get
let valueOfName = object[keyPath:name]複製代碼

經過索引能夠方便的進行KVC。git

KVO

遺憾的是依然只有 NSObject 才能支持 KVO。github

Swift 4中的一個對此有影響的改變是繼承 NSObject 的 swift class 再也不默認所有 bridge 到 OC。緣由能夠參考個人前一篇博客:Swift 4新知:自動清除冗餘代碼減少包大小。然而 KVO 又是一個純 OC 的特性,因此若是是 swift class 須要在聲明的時候增長 @objcMembers 關鍵字。不然在運行的時候你會獲得一個 error:web

fatal error: Could not extract a String from KeyPath Swift.ReferenceWritableKeyPath swift

另一件事就是被觀察的屬性須要用dynamic修飾,不然也沒法觀察到。api

一個好消息是不須要在對象被回收時手動 remove observer。可是這也帶來了另一個容易被忽略的事情:觀察的閉包沒有被強引用,須要咱們本身添加引用,不然當前函數離開後這個觀察閉包就會被回收了。閉包

@objcMembers class OCClass: NSObject {
    dynamic var name: String

    init(name: String) {
        self.name = name
    }
}

class ViewController: UIViewController {

    var swiftClass: OCClass!
    var ob: NSKeyValueObservation!

    override func viewDidLoad() {
        super.viewDidLoad()

        swiftClass = OCClass(name: "oc")
        ob = swiftClass.observe(\.name) { (ob, changed) in
            let new = ob.name
            print(new)
        }
        swiftClass.name = "swift4"
    }
}複製代碼

KVO 以後返回的是一個 NSKeyValueObservation 實例,須要本身控制這個實例的生命週期。app

參考:
Key Value Observation in iOS 11
smart key path
Re-enabling @objc inference within a class hierarchyide

歡迎關注個人微博:@沒故事的卓同窗

相關文章
相關標籤/搜索