iOS runtime消息轉(zhuǎn)發(fā)之objc_msgSend探究

引言

消息轉(zhuǎn)發(fā)的本質(zhì):向對(duì)象發(fā)送消息,是一個(gè)查找方法的過(guò)程。在前面我們研究過(guò)類(lèi),編譯成c++本質(zhì)是一個(gè)叫objc_classstruct指針

15033832-8973df891eda5a82.png

objc_class
里面有一個(gè)重要的成員cache_t障癌,用于方法的緩存。

查找方法的過(guò)程在底層即是一個(gè)根據(jù)sel找到imp的流程辩尊。

這里在探究消息轉(zhuǎn)發(fā)概念之前涛浙,不得不提到一個(gè)在Objective-C里面一個(gè)很重要的概念:runtime

  • 運(yùn)行時(shí)是相對(duì)于編譯時(shí)來(lái)說(shuō)的
  • 編譯時(shí)摄欲,主要是做一些詞法語(yǔ)法分析轿亮,也就是編譯時(shí)類(lèi)型檢查,編譯時(shí)刻代碼是不會(huì)被加載到內(nèi)存里胸墙。
  • 運(yùn)行時(shí):可執(zhí)行文件被裝載到內(nèi)存中我注,代碼跑起來(lái)了,會(huì)做運(yùn)行時(shí)檢查迟隅,但是和編譯時(shí)的檢查又不一樣但骨,不是簡(jiǎn)單的掃描代碼,而是在 內(nèi)存中做些操作智袭,做些判斷奔缠。

舉例如下:
創(chuàng)建兩個(gè)類(lèi)WJPersonWJTeacher,并且WJTeacher 繼承于WJPerson吼野。

WJTeacher:

    #import <Foundation/Foundation.h>
    #import "WJPerson.h"
    NS_ASSUME_NONNULL_BEGIN

    @interface WJTeacher : WJPerson
    //聲明并實(shí)現(xiàn)
    - (void)playFootball;
    //只聲明不實(shí)現(xiàn)校哎,在父類(lèi)實(shí)現(xiàn)
    - (void)playBasketball;

    @end

    NS_ASSUME_NONNULL_END

     #import "WJTeacher.h"

    @implementation WJTeacher


    - (void)playFootball{
        NSLog(@"%s",__func__);
    }

    @end

WJPerson:

    #import <Foundation/Foundation.h>

    NS_ASSUME_NONNULL_BEGIN

    @interface WJPerson : NSObject
    //這里方法沒(méi)帶參數(shù),有興趣的可以把帶參數(shù)的試試
    - (void)playBasketball;

    @end

    NS_ASSUME_NONNULL_END

   #import "WJPerson.h"

    @implementation WJPerson
    - (void)playBasketball{
        NSLog(@"%s",__func__);
    }


    @end

在main.m

   int main(int argc, const char * argv[]) {
       @autoreleasepool {
    
    WJTeacher *p  = [WJTeacher alloc];
    [p playFootball];
    [p playBasketball];


    
    }
   return 0;
}
   2021-07-01 16:43:14.786334+0800 KCObjcBuild[1925:49713] -[WJTeacher playFootball]
   2021-07-01 16:43:14.786870+0800 KCObjcBuild[1925:49713] -[WJPerson playBasketball]

分析如上代碼:在WJTeacher 我們只是聲明playBasketball方法瞳步,但是控制臺(tái)仍然顯示該方法調(diào)用成功闷哆。為什么會(huì)這樣腰奋?

首先:我們還是clang下這段代碼,看看編譯后到底是什么樣子阳准。

    int main(int argc, const char * argv[]) {
        /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 

            WJTeacher *p = ((WJTeacher *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("WJTeacher"), sel_registerName("alloc"));
            ((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("playFootball"));
            ((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("playBasketball"));

 //帶參數(shù)的-(void)playWithWhom:(NSString*)name;
    Dog*dog = ((Dog *(*)(id, SEL))(void *)objc_msgSend)((id)((Dog *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Dog"), sel_registerName("alloc")), sel_registerName("init"));
    ((void (*)(id, SEL, NSString *))(void *)objc_msgSend)((id)dog, sel_registerName("playWithWhom:"), (NSString *)&__NSConstantStringImpl__var_folders_4c_6y4z_qs972qgqg7g06frb7540000gn_T_main_48f0a4_mi_0);


        }
        return 0;
    }

從而引出了我們所要研究的主題:objc_msgSend

objc_msgSend

image.png

這里發(fā)現(xiàn)氛堕,objc_msgSend(void /* id self, SEL op, ... */ )方法雖然出來(lái)了馏臭,但是參數(shù)為空野蝇,需要進(jìn)行一步設(shè)置

image.png
image.png

結(jié)論:[p playFootball] 等價(jià)objc_msgSend(p,sel_registerName("playFootball"))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末括儒,一起剝皮案震驚了整個(gè)濱河市绕沈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌帮寻,老刑警劉巖乍狐,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異固逗,居然都是意外死亡浅蚪,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門(mén)烫罩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)惜傲,“玉大人,你說(shuō)我怎么就攤上這事贝攒〉撂埽” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵隘弊,是天一觀的道長(zhǎng)哈踱。 經(jīng)常有香客問(wèn)我,道長(zhǎng)梨熙,這世上最難降的妖魔是什么开镣? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮咽扇,結(jié)果婚禮上邪财,老公的妹妹穿的比我還像新娘。我一直安慰自己肌割,他們只是感情好卧蜓,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著把敞,像睡著了一般弥奸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上奋早,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天盛霎,我揣著相機(jī)與錄音赠橙,去河邊找鬼。 笑死愤炸,一個(gè)胖子當(dāng)著我的面吹牛期揪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播规个,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼凤薛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了诞仓?” 一聲冷哼從身側(cè)響起缤苫,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎墅拭,沒(méi)想到半個(gè)月后活玲,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谍婉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年舒憾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片穗熬。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡镀迂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出死陆,到底是詐尸還是另有隱情招拙,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布措译,位于F島的核電站别凤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏领虹。R本人自食惡果不足惜规哪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望塌衰。 院中可真熱鬧诉稍,春花似錦、人聲如沸最疆。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)努酸。三九已至服爷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仍源。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工心褐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人笼踩。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓逗爹,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親嚎于。 傳聞我的和親對(duì)象是個(gè)殘疾皇子掘而,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容