一、KVO (Key-Value Observing)
KVO 是 Objective-C 對觀察者模式(Observer Pattern)的實現。也是 Cocoa Binding 的基礎。當被觀察對象的某個屬性發生更改時,觀察者對象會獲得通知。
有意思的是,你不需要給被觀察的對象添加任何額外代碼,就能使用 KVO 。這是怎么做到的?
二、 KVO內部實現原理
- KVO是基於runtime機制實現的
- 當某個類的屬性對象
第一次被觀察時,系統就會在運行期動態地創建該類的一個派生類,在這個派生類中重寫基類中任何被觀察屬性的setter 方法。派生類在被重寫的setter方法內實現真正的通知機制 - 如果原類為Person,那么生成的派生類名為
NSKVONotifying_Person - 每個類對象中都有一個isa指針指向當前類,當一個類對象的第一次被觀察,那么系統會偷偷將isa指針指向動態生成的派生類,從而在給被監控屬性賦值時執行的是派生類的setter方法
- 鍵值觀察通知依賴於NSObject 的兩個方法:
willChangeValueForKey:和didChangevlueForKey:;在一個被觀察屬性發生改變之前,willChangeValueForKey:一定會被調用,這就 會記錄舊的值。而當改變發生后,didChangeValueForKey:會被調用,繼而observeValueForKey:ofObject:change:context:也會被調用。 -
補充:KVO的這套實現機制中蘋果還偷偷重寫了class方法,讓我們誤認為還是使用的當前類,從而達到隱藏生成的派生類
三、補充: 如何關閉默認的KVO的默認實現,並進入自定義的KVO實現?(看鏈接)
四、附注: KVC底層實現原理(如下)
KVC運用了一個isa-swizzling技術. isa-swizzling就是類型混合指針機制, 將2個對象的isa指針互相調換, 就是俗稱的黑魔法.
KVC主要通過isa-swizzling, 來實現其內部查找定位的. 默認的實現方法�由NSOject提供isa指針, 如其名稱所指,(就是is a kind of的意思), 指向分發表對象的類. 該分發表實際上包含了指向實現類中的方法的指針, 和其它數據。
- 具體主要分為三大步
- 第一步:尋找該屬性有沒有setsetter方法?有,就直接賦值
- 第二步:尋找有沒有該屬性帶下划線的成員屬性?有,就直接賦值
- 第三步:尋找有沒有該屬性的成員屬性?有,就直接賦值
- 或者這么說
- 1、首先搜索setKey:方法.(key指成員變量名, 首字母大寫)
- 2、上面的setter方法沒找到, 如果類方法accessInstanceVariablesDirectly返回YES. 那么按 _key, _isKey,key, iskey的順序搜索成員名.(NSKeyValueCodingCatogery中實現的類方法, 默認實現為返回YES)
- 3、如果沒有找到成員變量, 調用setValue:forUnderfinedKey:
比如說如下的一行KVC的代碼:
-
舉個🌰e.g:
[object setValue:@"13123" forKey:@"uuid"];
就會被編譯器處理成:
// 首先找到對應sel
SEL sel = sel_get_ uuid("setValue:forKey:");
// 根據object->isa找到sel對應的IMP實現指針
IMP method = objc_msg_lookup (object->isa,sel);
// 調用指針完成KVC賦值
method(object, sel, @"13123", @"uuid");
作者:Mg明明就是你
鏈接:https://www.jianshu.com/p/829864680648
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
作者:Mg明明就是你
鏈接:https://www.jianshu.com/p/829864680648
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
