KVO 就是key value observing (鍵值監聽 /觀察者模式)/是一種回調機制 觀察者模式 : 一個目標對象管理所有依賴於他的觀察者對象 /併在它自身的狀態改變時主動通知觀察者對象 /這個制動通知通常是通過調用各觀察者對象所提供的介面方法來實現的 /觀察者模式比較完美的將目標對象和觀 ...
KVO
就是key value observing (鍵值監聽 /觀察者模式)/是一種回調機制觀察者模式 :
一個目標對象管理所有依賴於他的觀察者對象 /併在它自身的狀態改變時主動通知觀察者對象 /這個制動通知通常是通過調用各觀察者對象所提供的介面方法來實現的 /觀察者模式比較完美的將目標對象和觀察者對象解耦簡單來說 :
在某個對象註冊監聽者後/在被監聽的對象發生改變時/對象會發送一個通知給監聽者/以便監聽者執行回調 就是每次指定的被觀察的對象的屬性被修改後 /KVO就會自動通知響應的觀察者 KVO和KVC一樣都依賴於Runtime的動態及時 /都屬於鍵值編程而且底層實現機制都是isa-swizzlingKVO運用 : 例-監聽scrollView的contentOffset屬性/來完成用戶滾動時動態改變某些控制項的屬性實現效果(包括漸變導航欄/下拉刷新控制項等效果)
KVO使用 : 要求-對象必須能支持KVC機制(NSobject的子類都支持)/(也就是說 賦值通過setter或者KVC)
方法-註冊 指定被觀察者的屬性 /實現回調方法 /移除觀察 適用-很適用模型屬性被修改後 / 引發 UIView的變化 /當更改屬性的值後 /監聽對象會立刻得到通知 當需要檢測其他類的屬性值變化 /但又不想被觀察的類知道 有點像FBI監視嫌疑人 /這個時候就可以使用KVO蘋果文檔對KVO的實現描述 :
Automatic key-value observing is implemented using a technique called isa-swizzling... When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class .. 也就是說/他使用的技術是ISA調和技術(isa-swizzling) /在我們對某個對象完成監聽註冊後/編譯器會修改所觀察到的對象的ISA指針 /可能還會修改了被監聽對象的某些屬性 /指向一個中間類而不是真正的類 /從某個意義來看 /這是一場騙局系統實現KVO的步驟:
- 當類A的對象第一次被觀察的時候,系統會在運行期動態創建類A的派生類。我們稱為B(NSKVONotifying_A)。
- 在派生類B(NSKVONotifying_A)中重寫類A的setter方法,B類在被重寫的setter方法中實現通知機制。
- 在這個過程中, 被觀察對象的isa指針從指向原來A類的, 被KVO機制修改為指向B(NSKVONotifying_A)類, 來實現當前類屬性值改變的監聽
- 類B(NSKVONotifying_A)重寫會 class方法,將自己偽裝成類A。類B還會重寫dealloc方法釋放資源。
- 系統將所有指向類A對象的isa指針指向類B的對象。
ISA指針 :
是一個指向Class類指針 /(專業術語是指向元類pointer to the metaclass 用來指向類的類型) /我們可以通過object_getClass方法來獲取這個值 /正常來說 class方法內部的實現就是獲取這個ISA指針代表的元類(metaclass) /但是在kvo機制中 /蘋果註冊監聽對象後 通過object_allocateClassPair動態重新創建了一個新類和元類 /此時object_getClass()獲取的就不是原來ISA指向的元類 /而是新建的元類 ISA指針的作用 :每個對象都有ISA指針 指向該對象的類 /他告訴Runtime系統這個對象的類是什麼 /所以對象註冊為觀察者時 /isa指針指向新類 /那麼這個被觀察者的對象就神奇的變成新子類的對象(或實例)了 /因而在該對象上對setting的調用就會調用已重寫的setter /從而激活鍵值通知機制重寫setter方法 :
新類重寫了setter方法解析 :KVO的鍵值觀察通知依賴於NSObject的兩個方法willChangeValueForKey /didChangeValueForKey 被觀察屬性發生變化之前 willChangeValueForKey被調用 /通知系統keyPath的屬性值即將改變 發生改變後 didChangeValueForKey被調用 /通知系統keyPath的屬性值已經改變 之後 - addObserver: forKeyPath: options: context 也會被調用 且重寫觀察屬性的setter方法這種繼承方式的註入是在運行時而不是編譯時實現的KVO實現步驟
(options通常傳- NSkeyValueObservingOptionNew|NSkeyValueObservingOptonOld) option是KVO里常見的參數 NSkeyValueObservingOption枚舉: NSkeyValueObservingOptionNew:提供更改前的值 NSkeyValueObservingOptionOld:提供更改後的值 NSkeyValueObservingOptionInitial:觀察最初的值(在註冊觀察服務的時候會調用一次觸發方法) NSkeyValueObservingOptionPrior:分別在值修改前後觸發方法(即一次修改兩次觸發 ) 註冊 (哪個要註冊KVO機制 / 觀察的屬性值 / 給你觀察鍵值變化的選擇 /方便傳輸你需要的數據 ) - addObserver: forKeyPath: options: context 實現(回調) (觀察的屬性值/object??? / 存儲了一些變化的數據 比如變化前的數據 變化後的數據 如果註冊時context不為空 這裡就能收到) - observeValueForKeyPath: ofObject: change: context: 移除 增加觀察與取消觀察是成對出現的 所以需要在最後的時候 移除觀察者(可以在- dealloc方法了寫) - removeObserver: forKeyPath: