KVO與KVC原理筆記

KVO的實現原理

當咱們對A類添加監聽的時候,系統會自動生成一個NSKVONotifying_A的子類,這個類重寫了A的class、superclass、deealloc方法和該屬性的Set方法,同時A類的對象的isa指針指向了該虛擬子類。當監聽屬性改變的時候系統調用NSSetobjectValueandNotify,這個方法的執行流程是(willchangeValueforkey->改變父類的值->didchangeValueforkey->observeValueForKey:ofObject:change:context:),若是設置automaticallyNotifiesObserversForKey:(NSString *)key爲NO的時候則須要手動觸發KVO即手動調用willchangeValueforkey和didchangeValueforkey.html

func _NSSetObjectValueAndNotify {
    ...
    willchangeValueforkey
    ...
    " objc_msgSendSupper '改變父類的值(猜想這樣實現) "
    ...
    didchangeValueforkey
    ...
    observeValueForKey:ofObject:change:context: 
}

複製代碼

Q1: 爲何重寫系統的class/superclass、deealloc方法

由於該子類爲系統自動生成蘋果想假裝成並無這個類 因此重寫class/superclass ,可是調用 objc_getClass()這個方法時候依然會暴露,由於這個方法是調用調用對象的isa指針指向。dealloc則是系統還有一些其餘的事情處理數組

Q2:爲何KVO要實現一個子類

KVC是什麼,他是如何實現的

KVCKVC是由NSKeyValueCoding非正式協議實現的一種機制,對象採用該協議來提供對其屬性的間接訪問。當一個對象符合鍵值編碼時,它的屬性能夠經過一個簡潔、統一的消息傳遞接口經過字符串參數來尋址。這種間接訪問機制補充了實例變量及其關聯的訪問方法所提供的直接訪問。bash

valueForkey的查找流程

  1. 在實例中搜索找到的類裏面的相關方法,其名稱依次爲get<Key>, <key>, is<Key>, or _<key>。若是找到,則調用它,並繼續執行步驟5的結果。不然繼續下一步。
  2. 若是沒有找到那麼搜索countOf<Key> and objectIn<Key>AtIndex:,若是找到了其中的第一個和另外兩個中的至少一個,則建立一個collection代理對象,該對象響應全部NSarray方法並返回該對象, 若是沒有找到數組相關方法那麼搜索countOf<Key>, enumeratorOf<Key>, and memberOf<Key>:,若是實現了其中一個則該對象響應全部Set方法的,
  3. 若是上述方法都沒有找到那麼判斷accessInstanceVariablesDirectly 屬性是否爲yes,若是爲yes則查找**_<key>, _is<Key>, <key>, or is<Key>**屬性,若是找到直接返回變量值
  4. 若是都沒找到那麼且accessInstanceVariablesDirectly爲false,那麼執行valueForUndefinedKey:方法,調用valueForUndefinedKey:,默認狀況下,這會引起異常,但NSObject的子類可能提供關鍵的特定行爲

setValueForkey的實現

set value:for key:的默認實現:給定key和value參數做爲輸入,嘗試在接收調用的對象內,使用如下過程將名爲key的屬性設置爲value(對於非對象屬性,則設置未包裝的value版本,如表示非對象值:app

  1. 按此順序查找名爲set<key> 和 **_set<key>**的第方法。若是找到了,使用value值調用它並完成。
  2. 若是找不到簡單訪問器,而且類方法accessInstanceVariablesDirectly返回Yes,則按該順序查找名爲 _<key>、_is<key>、<key>或is<key>的實例變量。若是找到,直接用value設置。
  3. 在找不到方法或實例變量時,調用setValue:ForUndefinedKey:。默認狀況下,這會引起異常,但NSObject的子類可能提供關鍵的特定行爲。
相關文章
相關標籤/搜索