深刻理解 KVC\KVO 實現機制 — KVO

KVC和KVO都屬於鍵值編程並且底層實現機制都是isa-swizzing,因此原本想放在一塊兒講的。可是篇幅有限因此就分紅了兩篇博文。 KVC實現機制傳送門html

KVO概述

鍵值觀察Key-Value-Observer就是觀察者模式。編程

  • 觀察者模式的定義:一個目標對象管理全部依賴於它的觀察者對象,並在它自身的狀態改變時主動通知觀察者對象。這個主動通知一般是經過調用各觀察者對象所提供的接口方法來實現的。觀察者模式較完美地將目標對象與觀察者對象解耦。

當須要檢測其餘類的屬性值變化,但又不想被觀察的類知道,有點像FBI監視嫌疑人,這個時候就可使用KVO了。指針

KVO同KVC同樣都依賴於Runtime的動態機制code

KVO實現步驟

  • 註冊
//keyPath就是要觀察的屬性值
//options給你觀察鍵值變化的選擇
//context方便傳輸你須要的數據
-(void)addObserver:(NSObject *)anObserver 
        forKeyPath:(NSString *)keyPath 
           options:(NSKeyValueObservingOptions)options 
           context:(void *)context
  • 實現方法
//change裏存儲了一些變化的數據,好比變化前的數據,變化後的數據;若是註冊時context不爲空,這裏context就能接收到。
-(void)observeValueForKeyPath:(NSString *)keyPath 
                     ofObject:(id)object
                       change:(NSDictionary *)change 
                      context:(void *)context
  • 移除
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

KVO的實現分析

使用觀察者模式須要被觀察者的配合,當被觀察者的狀態發生變化的時候經過事先定義好的接口(協議)通知觀察者。在KVO的使用中咱們並不須要向被觀察者添加額外的代碼,就能在被觀察的屬性變化的時候獲得通知,這個功能是如何實現的呢?同KVC同樣依賴於強大的Runtime機制。server

系統實現KVO有如下幾個步驟:htm

  • 當類A的對象第一次被觀察的時候,系統會在運行期動態建立類A的派生類。咱們稱爲B。
  • 在派生類B中重寫類A的setter方法,B類在被重寫的setter方法中實現通知機制。
  • 類B重寫會 class方法,將本身假裝成類A。類B還會重寫dealloc方法釋放資源。
  • 系統將全部指向類A對象的isa指針指向類B的對象。

KVO同KVC同樣,經過 isa-swizzling 技術來實現。當觀察者被註冊爲一個對象的屬性的觀察對象的isa指針被修改,指向一箇中間類,而不是在真實的類。其結果是,isa指針的值並不必定反映實例的實際類。對象

因此不能依靠isa指針來肯定對象是不是一個類的成員。應該使用class方法來肯定對象實例的類。blog

相關文章
相關標籤/搜索