kvo 與 kvc <2>

8.1: kvo 與 kvc 展開(kāi)

? ? ?1:KVO

? ? ? ? ? ? KVO(Key-Value-Observing)鍵值觀察,其技術(shù)原理就是通過(guò) isa waizzle 技術(shù)添加被觀察對(duì)象中間類,并重新寫相應(yīng)的方法來(lái)監(jiān)聽(tīng)鍵值變化。當(dāng)被觀察的對(duì)象屬性被修改后,則對(duì)象回接收到通知,即每次指定的被觀察對(duì)象的屬性被修改后,kvo就會(huì)自動(dòng)通知相應(yīng)的觀察者。

? ? ? ? ? ? isa swizzle 不同于method swizzle,其交換的是isa,對(duì)象的isa 指針式定義了它的類,所以ISA swizzling 指修改對(duì)象所指向的類,KVO則是使用該技術(shù)實(shí)現(xiàn)的,還有zombie objects檢測(cè)也用到了該技術(shù),而method swizzle交換的是method

? ? ? ? 2:KVO引起的crash 情況如下

? ? ? ? ? ? 2.1* observer 已銷毀,但是未及時(shí)移除監(jiān)聽(tīng);

? ? ? ? ? ? 2.2* addObserver 與 removeObserver 不匹配

? ? ? ? ? ? ? ? 1:移除了未注冊(cè)的觀察者,但是未及時(shí)移除監(jiān)聽(tīng)

? ? ? ? ? ? ? ? 2:重復(fù)移除多次,移除次數(shù)多于添加次數(shù),導(dǎo)致崩潰。

? ? ? ? ? ? ? ? 3:重復(fù)添加多次,雖然不會(huì)崩潰,但是發(fā)生改變時(shí),也同時(shí)會(huì)被觀察多次。

? ? ? ? ? ? 2.3*添加了觀察者,但未實(shí)現(xiàn)observerValueForKeyPath:ofObject:change:context: 方法,導(dǎo)致崩潰.

? ? ? ? ? ? 2.4*添加或移除時(shí) keypath == nil ,導(dǎo)致崩潰.

? ? ? ? 通過(guò)如上場(chǎng)景就可以發(fā)現(xiàn)其實(shí)kvo 崩潰的主要原因是觀察者管理混亂,特別是觀察者關(guān)系復(fù)雜時(shí),開(kāi)發(fā)者容易導(dǎo)致混亂。

? ? ? ? ? ? 如下圖所示:


圖1


? ? ? ? 那如何管理呢? 既然觀察者都是開(kāi)發(fā)者來(lái)管理,由人來(lái)管理必然會(huì)出現(xiàn)失誤的時(shí)候,那我們是否能通過(guò)一個(gè)代理對(duì)象來(lái)管理?

? ? ? ? ? ? 答案:yes!

圖2


? ? ? ? 3:具體實(shí)現(xiàn)如下:

? ? ? ? ? ? 1:通過(guò)Method Swizzle方法調(diào)配交換KVO相應(yīng)的方法到NSObject基類,如下:

圖3

? ? ? ? ? ? 2: 然后在觀察者和被觀察者之間建立一個(gè) KVODelegate 對(duì)象,

? ? ? ? ? ? ? ? 兩者之間通過(guò) KVODelegate 對(duì)象 建立聯(lián)系。然后在添加和移除操作時(shí),

? ? ? ? ? ? ? ? 將 KVO 的相關(guān)信息例如 observer、keyPath、options、context 保存為 KVOInfo 對(duì)象,并添加到 KVODelegate 對(duì)象 中對(duì)應(yīng) 的 關(guān)系哈希表 中,對(duì)應(yīng)原有的添加觀察者。

? ? ? ? ? ? 3: 在添加和移除操作的時(shí)候,

? ? ? ? ? ? ? ? 利用 KVODelegate 對(duì)象 做轉(zhuǎn)發(fā),

? ? ? ? ? ? ? ? 把真正的觀察者變?yōu)?KVODelegate 對(duì)象,

? ? ? ? ? ? ? ? 而當(dāng)被觀察者的特定屬性發(fā)生了改變(會(huì)被調(diào)用到observeValueForKeyPath:ofObject),

? ? ? ? ? ? ? ? 再由 KVODelegate 對(duì)象分發(fā)到原有的觀察者上。

? ? ? ? ? ? 4:為了避免被觀察者提前被釋放,

? ? ? ? ? ? ? ? 被觀察者在 dealloc 時(shí)仍然注冊(cè)著 KVO 導(dǎo)致崩潰。

? ? ? ? ? ? ? ? BayMax 系統(tǒng)還利用 Method Swizzling 實(shí)現(xiàn)了自定義的 dealloc,

? ? ? ? ? ? ? ? 在系統(tǒng) dealloc 調(diào)用之前,將多余的觀察者移除掉。

? 8.1.2:KVC

? ? ? KVC(Key Value Coding)鍵值編碼,提供一種機(jī)制來(lái)間接訪問(wèn)對(duì)象的屬性,而不是通過(guò)Setter/Getter方法進(jìn)行訪問(wèn)。

? ? ? 通常導(dǎo)致崩潰的原因不外乎鍵值設(shè)置不正確,如下:

? ? ? ? ? 1. key 不是對(duì)象的屬性

? ? ? ? ? 2. keyPath 不正確

? ? ? ? ? 3. value 為 nil,為非對(duì)象設(shè)值

? ? ? ? ? 4. key 為 nil

? ? ? 那如何防護(hù)呢,熟悉KVC機(jī)制的同學(xué)肯定清楚:runtime提供了相應(yīng)的補(bǔ)救措施來(lái)避免應(yīng)用崩潰,包括如下:

? ? ? ? ? ? setValue:forKey: 找不到相應(yīng)的key會(huì)調(diào)用 setValue: forUndefinedKey: 方法;

? ? ? ? ? ? valueForKey: 找不到相應(yīng)的keyPath會(huì)調(diào)用 valueForUndefinedKey: 方法;

? ? ? ? ? ? setValue:forKey:添加value為nil方法,會(huì)調(diào)用setNilValueForKey方法來(lái)避免;


? ? ? 因此,針對(duì)上面崩潰的前3中場(chǎng)景,就可以通過(guò)分辨實(shí)現(xiàn)上述三種方法來(lái)避免,但對(duì)于key為nil的情況該如何防護(hù)呢?

? ? ? ? ? ? 這里直接告訴答案:毅然是通過(guò)熟悉的Method Swizzle來(lái)替換原有的

? ? ? ? ? ? setValue:forKey:方法,

? ? ? ? ? ? 并判斷傳入的key是否為nil。具體代碼如下:


圖4
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • KVO(Key-Value-Observing)鍵值觀察,其技術(shù)原理就是通過(guò)isa swizzle技術(shù)添加被觀察對(duì)...
    YanZi_33閱讀 1,568評(píng)論 0 2
  • KVO屬性依賴 看一個(gè)例子:我們的模型類 LabColor 代表一種 lab色彩空間里的顏色。和 RGB 不同,這...
    毅個(gè)天亮閱讀 812評(píng)論 0 1
  • KVC: 定義: KVC全稱是Key Value Coding(鍵值編碼),是一個(gè)基于NSKeyValueCodi...
    飛哥漂流記閱讀 1,306評(píng)論 0 0
  • 本文對(duì) KVC、KVO 相關(guān)知識(shí)進(jìn)行全面的整理總結(jié),介紹了相關(guān)的基本概念、使用方法、注意事項(xiàng)、實(shí)現(xiàn)原理等。后續(xù)如有...
    z4ywzrq閱讀 668評(píng)論 0 2
  • #pragma clang diagnostic push #pragma clang diagnostic ig...
    戀空K閱讀 327評(píng)論 0 1

友情鏈接更多精彩內(nèi)容