KVO接口說明
注冊:addObserver:forKeyPath:options:context:
例如
[self.busModel ?addObserver: self ?forKeyPath: @"name" options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOldcontext:@"bus name"];
1>.self.busModel :要監聽的對象
2>.self 觀察者,負責處理監聽事件的對象
3>.監聽的屬性
4>.觀察的選項(例如新值)
5>.上下文,用于傳遞數據,可以利用它區分不同的監聽
屬性改變時調用的方法
- (void)observeValueForKeyPath:(NSString *)keyPath ? ofObject:(id)object ?change:(NSDictionary *)change ? context:(void*)context
1>.監聽的屬性
2>.屬性所屬對象
3>.屬性的變化
4>.上下文
Apple的文檔對 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-swizzling(isa混編)來實現的
其實當我們觀察一個對象時,會動態的創建一個新類,這個類繼承與我們所觀察的對象所在的類,并重寫了觀察對象的屬性的setter方法,在setter方法中實現真正的通知機制:
如圖:
1.每個類對象中都有一個isa指針指向當前類,當一個類對象的第一次被觀察,那么系統會偷偷將isa(isa 指針告訴 Runtime 系統這個對象的類是什么)指針指向動態生成新類,從而在給被監控屬性賦值時執行的是派生類的setter方法
2.鍵值觀察通知依賴于 NSObject 的兩個方法:willChangeValueForKey:和didChangevlueForKey:。在一個被觀察屬性發生改變之前,willChangeValueForKey:一定會被調用,這就會記錄舊的值。而當改變發生后didChangeValueForKey:也會被調用,在observers列表中檢查是否有該屬性,有的話observeValueForKey:ofObject:change:context:也會被調用
經測試observeValueForKey是在didChangeValueForKey執行時調用的