KVO在Apple中的API文檔如下:
KVO基本原理:
1.KVO是基於runtime機制實現的
2.當某個類的屬性對象第一次被觀察時,系統就會在運行期動態地創建該類的一個派生類,在這個派生類中重寫基類中任何被觀察屬性的setter 方法。派生類在被重寫的setter方法內實現真正的通知機制
3.如果原類爲Person,那麼生成的派生類名爲NSKVONotifying_Person
4.每個類對象中都有一個isa指針指向當前類,當一個類對象的第一次被觀察,那麼系統會偷偷將isa指針指向動態生成的派生類,從而在給被監控屬性賦值時執行的是派生類的setter方法
5.鍵值觀察通知依賴於NSObject 的兩個方法: willChangeValueForKey: 和 didChangevlueForKey:;在一個被觀察屬性發生改變之前, willChangeValueForKey:一定會被調用,這就 會記錄舊的值。而當改變發生後,didChangeValueForKey:會被調用,繼而 observeValueForKey:ofObject:change:context: 也會被調用。
KVO深入原理:
1.Apple 使用了 isa 混寫(isa-swizzling)來實現 KVO 。當觀察對象A時,KVO機制動態創建一個新的名爲: NSKVONotifying_A的新類,該類繼承自對象A的本類,且KVO爲NSKVONotifying_A重寫觀察屬性的setter 方法,setter 方法會負責在調用原 setter 方法之前和之後,通知所有觀察對象屬性值的更改情況。
2.NSKVONotifying_A類剖析:在這個過程,被觀察對象的 isa 指針從指向原來的A類,被KVO機制修改爲指向系統新創建的子類 NSKVONotifying_A類,來實現當前類屬性值改變的監聽;
3.所以當我們從應用層面上看來,完全沒有意識到有新的類出現,這是系統“隱瞞”了對KVO的底層實現過程,讓我們誤以爲還是原來的類。但是此時如果我們創建一個新的名爲“NSKVONotifying_A”的類(),就會發現系統運行到註冊KVO的那段代碼時程序就崩潰,因爲系統在註冊監聽的時候動態創建了名爲NSKVONotifying_A的中間類,並指向這個中間類了。
4.(isa 指針的作用:每個對象都有isa 指針,指向該對象的類,它告訴 Runtime 系統這個對象的類是什麼。所以對象註冊爲觀察者時,isa指針指向新子類,那麼這個被觀察的對象就神奇地變成新子類的對象(或實例)了。) 因而在該對象上對 setter 的調用就會調用已重寫的 setter,從而激活鍵值通知機制。
5.子類setter方法剖析:KVO的鍵值觀察通知依賴於 NSObject 的兩個方法:willChangeValueForKey:和 didChangevlueForKey:,在存取數值的前後分別調用2個方法:被觀察屬性發生改變之前,willChangeValueForKey:被調用,通知系統該 keyPath 的屬性值即將變更;當改變發生後, didChangeValueForKey: 被調用,通知系統該 keyPath 的屬性值已經變更;之後, observeValueForKey:ofObject:change:context: 也會被調用。且重寫觀察屬性的setter 方法這種繼承方式的注入是在運行時而不是編譯時實現的。