Runtime 簡(jiǎn)介:
Runtime 又叫運(yùn)行時(shí)衫生,是一套底層的 C 語(yǔ)言 API凹炸,其為 iOS 內(nèi)部的核心之一,我們平時(shí)編寫的 OC 代碼懒熙,底層都是基于它來(lái)實(shí)現(xiàn)的丘损。
與Runtime交互
Objc 從三種不同的層級(jí)上與 Runtime 系統(tǒng)進(jìn)行交互,分別是通過(guò) Objective-C 源代碼工扎,通過(guò) Foundation 框架的NSObject類定義的方法徘钥,通過(guò)對(duì) runtime 函數(shù)的直接調(diào)用。
Runtime 是什么:
1.運(yùn)行時(shí)(Runtime)是指將數(shù)據(jù)類型的確定由編譯時(shí)推遲到了運(yùn)行時(shí)肢娘。
2.Runtime是一套比較底層的純C語(yǔ)言API, 屬于1個(gè)C語(yǔ)言庫(kù), 包含了很多底層的C語(yǔ)言API呈础。
3.平時(shí)編寫的OC代碼舆驶,在程序運(yùn)行過(guò)程中,其實(shí)最終會(huì)轉(zhuǎn)換成Runtime的C語(yǔ)言代碼而钞,Runtime是Object-C的幕后工作者沙廉。
4.Object-C需要Runtime來(lái)創(chuàng)建類和對(duì)象,進(jìn)行消息發(fā)送和轉(zhuǎn)發(fā)臼节。
特性:?編寫的代碼具有運(yùn)行時(shí)撬陵、動(dòng)態(tài)特性。
Runtime用來(lái)干什么官疲?用在哪些地方袱结?
用來(lái)干什么 基本作用
1.在程序運(yùn)行過(guò)程中,動(dòng)態(tài)的創(chuàng)建類途凫,動(dòng)態(tài)添加垢夹、修改這個(gè)類的屬性和方法;
2.遍歷一個(gè)類中所有的成員變量维费、屬性果元、以及所有方法;
3.消息傳遞犀盟、轉(zhuǎn)發(fā)而晒;
4.方法調(diào)配;
5.“類對(duì)象” NSProxy阅畴;
6.KVC倡怎、KVO ;
用在哪些地方 Runtime的典型事例
1.給系統(tǒng)分類添加屬性贱枣、方法监署;
2.方法交換;
3.獲取對(duì)象的屬性纽哥、私有屬性钠乏;
4.字典轉(zhuǎn)換模型;
5.KVC春塌、KVO;
6.歸檔(編碼晓避、解碼);
7.NSClassFromString class<->字符串
8.block;
9.類的自我檢測(cè);
10.Aspects(AOP必備,“取締” baseVC只壳,無(wú)侵入埋點(diǎn))
消息轉(zhuǎn)發(fā)機(jī)制
當(dāng)向某個(gè)對(duì)象發(fā)送一條消息時(shí)俏拱,若該對(duì)象的方法列表以及它相應(yīng)繼承鏈上的方法列表都無(wú)法找到以該消息選擇子作為key的方法實(shí)現(xiàn)時(shí),則會(huì)觸發(fā)消息轉(zhuǎn)發(fā)機(jī)制吼句。
1.動(dòng)態(tài)方法解析?+ (BOOL)resolveInstanceMethod:(SEL)sel;
當(dāng)接受到未能識(shí)別的選擇子時(shí)彰触,運(yùn)行時(shí)系統(tǒng)會(huì)調(diào)用該函數(shù)用以給對(duì)象一次機(jī)會(huì)來(lái)添加相應(yīng)的方法實(shí)現(xiàn),如果用戶在該函數(shù)中動(dòng)態(tài)添加了相應(yīng)方法的實(shí)現(xiàn)命辖,則跳轉(zhuǎn)到方法的實(shí)現(xiàn)部分况毅,并將該實(shí)現(xiàn)存入緩存中分蓖,以供下次調(diào)用。
2.備用接收者??- (id)forwardingTargetForSelector:(SEL)aSelector;
如果運(yùn)行時(shí)在消息轉(zhuǎn)發(fā)的動(dòng)態(tài)方法解析中未找到所調(diào)用方法的實(shí)現(xiàn)尔许,那么當(dāng)前接收者還有第二次機(jī)會(huì)進(jìn)行未知選擇子的處理么鹤。這時(shí)運(yùn)行期系統(tǒng)會(huì)調(diào)用上述方法,并將未知選擇子作為參數(shù)傳入味廊,該方法可以返回一個(gè)能處理該選擇子的對(duì)象蒸甜,運(yùn)行時(shí)系統(tǒng)會(huì)根據(jù)返回的對(duì)象進(jìn)行查找,若找到則跳轉(zhuǎn)到相應(yīng)方法的實(shí)現(xiàn)余佛,則消息轉(zhuǎn)發(fā)結(jié)束柠新。
3.完整的消息轉(zhuǎn)發(fā)??- (void)forwardInvocation:(NSInvocation *)anInvocation;
當(dāng)運(yùn)行時(shí)系統(tǒng)檢測(cè)到備援接收者中用戶未返回能處理相應(yīng)選擇子的對(duì)象時(shí),那么來(lái)到這一步就要啟動(dòng)完整的消息轉(zhuǎn)發(fā)機(jī)制了辉巡。該方法可以改變消息調(diào)用目標(biāo)恨憎,運(yùn)行時(shí)系統(tǒng)根據(jù)所改變的調(diào)用目標(biāo),向調(diào)用目標(biāo)方法列表中查詢對(duì)應(yīng)方法的實(shí)現(xiàn)并實(shí)現(xiàn)跳轉(zhuǎn)郊楣,這種方式和備用接收者步的操作非常相似憔恳。當(dāng)然你也可以修改方法的選擇子,亦或者向所調(diào)用方法中追加一個(gè)參數(shù)等來(lái)跳轉(zhuǎn)到相關(guān)方法的實(shí)現(xiàn)净蚤。
最后钥组,如果消息轉(zhuǎn)發(fā)的第3步還未能處理該未知選擇子的話,那么最終會(huì)調(diào)用NSObject類的如下方法用以異常的拋出今瀑,表明該選擇子最終未能處理程梦。
- (void)doesNotRecognizeSelector:(SEL)aSelector;
附上完整的消息轉(zhuǎn)發(fā)流程圖: