隨着 keypath 獲得加強,KVC 和 KVO 的 API 都有了一些進化。html
一個感人的進步就是 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
遺憾的是依然只有 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
歡迎關注個人微博:@沒故事的卓同窗