KVOController

KVOController是目前OC上用的最多的KVO的第三方庫,facebook出品。有以下特點:

  • 提供block方式和selector方式,不需要實現(xiàn)observeValueForKeyPath:ofObject:change:context:
  • 不需要關(guān)心context,keyPath等參數(shù)來判斷是哪個觀察者的事件
  • 在某些情況下,不需要手動移除觀察者

本文主要探討以下內(nèi)容:

1. 類之間的引用關(guān)系
2. 什么情況可以自動移除觀察者,不需要開發(fā)者關(guān)心
3. KVOControllerNonRetaining
4. 實際開發(fā)中怎么用更方便

類之間的引用關(guān)系

如下圖所示:

  1. 調(diào)用者持有KVOController,并調(diào)用KVOController中的observe:keyPath:options:block:方法注冊觀察者,并在block中處理自己的業(yè)務(wù)
  2. _FBKVOInfo記錄調(diào)用者的信息,并作為context上下文參數(shù)傳遞。當(dāng)收到系統(tǒng)回調(diào)時取出該上下文,并回調(diào)給調(diào)用者
  3. _FBKVOSharedController是一個單例,真正調(diào)用系統(tǒng)addObserver的觀察者
  4. NSObject+FBKVOController分類中提供兩個屬性,KVOControllerKVOControllerNonRetaining
    4.1 這兩個屬性都是strong引用,即調(diào)用者會強引用KVOController
    4.2 KVOController表示觀察者也是強引用的
    4.3 KVOControllerNonRetaining表示觀察者是弱引用
類引用關(guān)系.png

理想情況下的自動解除KVO

從上圖可以看到,KVOController唯一被強引用的地方就是self(observer)。所以,只要self對象被釋放,KVOController隨后就會被釋放。在KVOControllerdealloc方法中,調(diào)用了unobserveAll,從而實現(xiàn)了自動移除所有觀察者的功能。

現(xiàn)實總是殘酷的,總有可能不小心導(dǎo)致self對象釋放不了,如:

  1. block中使用了self,導(dǎo)致block強引用self,此時調(diào)用者就無法自動釋放了
  2. 被觀察者是self,此時KVOController_objectInfosMap屬性中的key即為self,且是強引用的,所以調(diào)用者也無法釋放

KVOControllerNonRetaining

在上面的被觀察者是self的情況時,可能有人注意到了在 NSObject+FBKVOController分類中提供了一個屬性:KVOControllerNonRetaining。是不是可以用這個屬性就可以做到自動移除觀察者了呢?
答案是否定的,這種情況依然無法移除觀察者,而且會造成崩潰。
這是因為:

  1. KVOControllerNonRetaining表示_objectInfosMap屬性中的key為弱引用。
  2. 此時observer == observed == self
  3. 當(dāng)self被釋放時,KVOControllerNonRetaining會執(zhí)行dealloc中的unobserveAll,由于_objectInfosMap屬性中的key為弱引用,NSMapTable會自動清除該鍵值對,所以永遠(yuǎn)移除不了觀察者。而self對象,由于還依然存在著注冊的觀察者(_FBKVOSharedController),最終導(dǎo)致崩潰。

回歸實際

從我個人實際的開發(fā)角度而言,self通常既是我的觀察者,也是我的被觀察者,因為就算我觀察的不是類本身的屬性,也通常是我類的屬性的屬性。而此時我通常喜歡使用被觀察者是self的原因是OC提供的Keypath方式,通過FBKVOKeyPath宏可以方便的進(jìn)行點.操作,如FBKVOKeyPath(self.clock.date)。
所以FBKVOController對我而言,常用的方式是:

  1. 使用分類中的KVOController屬性
  2. 調(diào)用帶block的方法
  3. 手動移除觀察者
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • KVO 作為 iOS 中一種強大并且有效的機制,為 iOS 開發(fā)者們提供了很多的便利;我們可以使用 KVO 來檢測...
    JzRo閱讀 1,076評論 0 2
  • KVO在MVC架構(gòu)的項目中是一種特別有用的技術(shù)。KVOController建立在Cocoa經(jīng)受時間考驗的KVO實現(xiàn)...
    西瓜冰s閱讀 5,372評論 0 6
  • 前言 在閱讀公司源碼的一些功能時發(fā)現(xiàn)了KVOController這個神奇的庫。這個庫十分的好用,可以主動的去觀察一...
    QYiZHong閱讀 558評論 0 1
  • 簡介 鍵值觀察是模型 - 視圖 - 控制器應(yīng)用程序(MVC)中各層之間通信的一種特別有用的技術(shù)。 KVOContr...
    MichaelLedger閱讀 2,462評論 0 9
  • 因為https://blog.csdn.net/urdfmqcul2/article/details/787889...
    蘇大盒子閱讀 1,358評論 4 3

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