在Swift中使用KVO的細節以及內部實現解析

在文字的開頭,先說一個小細節,swift中聲明一個類,你能夠集成自NSObject,也能夠選擇忽略,兩者有什麼區別呢。根據本身的經驗,我得出如下結論。不足之處,請指出。exmple:咱們聲明這樣一個類swift

class Person: NSObject {
    var name: String?
    override init() {
        super.init()
    }
}
此類打印出的內存地址是0x00000fbd00007ffeefbfc240
複製代碼

這段代碼是不會報錯的,是一個典型的swift遺留ObjC語法的寫法,可是若是咱們去掉NSObject並打印出他的內存地址,以下數組

class Person {
    var name: String?
    init() {
        
    }
}
此類打印出的內存地址是0x00007ffeefbfc240
複製代碼
  • 內存地址不同,繼承自NSObject的類對象的內存地址明顯長度多了8個長度,why?多出的8個空間就是爲了存放ObjC對象內的isa指針,有興趣的能夠往下研究。
  • 繼承自NSObject的類可使用OC裏的一些騷操做,好比KVC、KVO、runtime,不然使用setValue-forKey時是會報錯的。

區別還有不少,平時在開發中你們能夠多注意這一區別。我的偏向不繼承NSObject,尤爲是我須要此類作一些騷操做時,好比KVO。bash

KVO是OC一個對象屬性的特性,因爲是面向字符串,因此開發時須要尤爲當心,這種奔潰只有執行到了纔會報錯。 聲明以下類:ide

class Person: NSObject {
     @objc var age: Int?
     var name: String?
     var observation: NSKeyValueObservation?
     
     override init() {
        super.init()
        self.observation = observe(\Person.age, options: .new, changeHandler: { (person, change) in
            print("Person.age的新值 = ", change.newValue as Any)
        })
    }
}
複製代碼

在外部咱們,初始化一個對象,並對age進行賦值,以下ui

let person = Person()
person.age = 18
person.setValue(100, forKey: "age")
複製代碼

程序執行後,(ÒωÓױ)!爲何只有一個打印?按理說是應該打印Person.age的新值 = 18Person.age的新值 = 100的呀,然而並無😆。問題出在哪,原來,swift中若是須要對一個值進行監聽,那麼必定要記住2個關鍵詞spa

  • @objc
  • dynamic

不然,指針

沒有@objc程序在監聽時會觸發奔潰code

沒有dynamic則屬性的set方法不會生效,天然就沒有上面的打印,由於KVO的本質就是監聽屬性的set方法,而可變數組的增刪操做都不會生效;對象

可是爲何KVC的操做卻能生效呢? 這是由於KVC內部的實現過程是繼承

  • [person willChangeValueForKey:@"age"];
  • person->_age = 10;
  • [person didChangeValueForKey:@"age"];
  • 而didChangeValueForKey:內部會調用observe的observeValueForKeyPath:ofObject:change:context:的方法,也就觸發了KVO

因此正確的寫法應該是

class Person: NSObject {
     @objc dynamic var age: Int?
     var name: String?
     var observation: NSKeyValueObservation?
     
     override init() {
        super.init()
        self.observation = observe(\Person.age, options: .new, changeHandler: { (person, change) in
            print("Person.age的新值 = ", change.newValue as Any)
        })
    }
}
複製代碼
相關文章
相關標籤/搜索