OC消息傳遞機制

前言

Object-C是一門動態(tài)語言,Rumtime更是OC動態(tài)特性中最重要的一部分,今天我們就來深入了解一下 Runtime中的消息傳遞機制

首先我們要區(qū)分兩個概念,編譯時,運行時

編譯時:編譯時只是對語言進行最基本的檢查報錯,包括詞法分析、語法分析等等 我們?nèi)粘i_發(fā)中用的 OC 、 Swift、 Java 等等都是高級語言,(高級語言 可閱讀性強)但是不被計算機識別,所以編譯就可以把高級語言編譯成計算機可識別的匯編語言 系統(tǒng)所識別的二進制 ,但是編譯成功 不代表可以運行。

運行時:運行時即程序通過了編譯之后編譯好的代碼被裝載到內(nèi)存中跑起來的階段,這個時候會具體對類型進行檢查,而不僅僅是對代碼的簡單掃描分析,此時若出錯程序會崩潰。

現(xiàn)在我創(chuàng)建了一個TestClass的類 定義了一個名為run的實例方法沒有在.M中實現(xiàn) 。然后在main函數(shù)中調(diào)用,很顯然在編譯時沒有沒有報錯。

#import <Foundation/Foundation.h>

@interface TestClass : NSObject

- (void)run;

@end
int main(int argc, char * argv[]) {
    @autoreleasepool {
        TestClass *class =[[TestClass alloc]init];
        [class run];
    }
}

雖然沒有對應(yīng)run方法的實現(xiàn),但是編譯通過了,并沒有爆出錯誤,從而證明OC的動態(tài)特性, 方法的實際調(diào)用是在運行時進行的,通過動態(tài)綁定機制來決定需要調(diào)用的方法。

objc_msgSend()函數(shù)

void objc_msgSend(id self, SEL cmd, ...)

在OC中調(diào)用方法 我們可以看做就是給某個對象發(fā)送消息 而objc_msgSend()函數(shù)就是其中最核心的發(fā)送消息函數(shù)
這是一個參數(shù)個數(shù)可變的函數(shù)。能接收兩個或兩個以上的參數(shù),第一個參數(shù)代表接受者,第二個參數(shù)代表方法名。后續(xù)參數(shù)就是消息中的那些參數(shù),其順序不變。接受者就是調(diào)用方法的對象或者類(本質(zhì)上類也是對象,叫做類對象)。運行時,上面Objc的方法調(diào)用會被翻譯成一條C語言的函數(shù)調(diào)用,如下:

objc_msgSend(class,  @selector(run))

消息傳遞流程

當調(diào)用objc_msgSend()函數(shù)會經(jīng)歷以下過程

1.從緩存中查找對應(yīng)SEL(封裝后方法名)的IMP (指向函數(shù)實現(xiàn)的指針)

被調(diào)用過的方法會存在緩存里面,每個類都會有一個表來存被調(diào)用過的方法,以便下次更快的調(diào)用。(這個是比較快速的)

2.從方法列表中查找

接受者會通過isa 找到自己的元類(metaClass),從元類的方法列表繼續(xù)查找對應(yīng)SEL(方法名)的IMP 如果找到則寫入緩存,調(diào)用。如果沒有找到再從父類中查找方法,如此往復(fù),直到達到基類。如果找不到則執(zhí)行方法的動態(tài)解析。

3.消息轉(zhuǎn)發(fā)機制--動態(tài)解析

調(diào)用

 + (BOOL)resolveInstanceMethod:(SEL)sel

方法來查看是否能夠返回一個selector,如果存在則返回selector。不存在進入下一步。

4.備用接受者
- (id)forwardingTargetForSelector:(SEL)aSelector

這個方法來詢問是否有接受者可以接受這個方法呀。如果有人接受,則交給它處理,就好像一切都沒發(fā)生過一樣。

5.完整轉(zhuǎn)發(fā)機制--消息重定向

如果到這一步還不能夠找到相應(yīng)的Selector的話,就要進行完整的方法轉(zhuǎn)發(fā)過程。調(diào)用方法

-(void)forwardInvocation:(NSInvocation *)anInvocation

最后還是沒有找到的話就會爆出unrecognized selector sent to instance 0x100111df0'的錯誤就來了。

以上就是消息傳遞機制的全部流程
至于第三步消息轉(zhuǎn)發(fā)機制的詳細流程會在之后的文章詳細說明 最后放上一張關(guān)于元類(metaClass)的詳細關(guān)系圖

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容