IOS-詳解KVO底層實現


一、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
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM