理解objc_msgSend的作用

“好記性不如爛筆頭”闷串,雖然我不是用的筆祖搓。但是敲一遍對我來說效果肯定比單純的看一遍效果更好S狻!拯欧!


在對象上調(diào)用方法是OC中經(jīng)常使用的功能详囤,用OC的術(shù)語來說這叫做“傳遞消息”。消息有“名稱(name)”和“選擇子(selector)”镐作,可以接受參數(shù)藏姐,也可以返回值。

OC是C的超集该贾,C語言使用“靜態(tài)綁定”羔杨,也就是說在編譯期就能決定運(yùn)行時(shí)所應(yīng)調(diào)用的函數(shù)。如下代碼:

圖1

如果不考慮內(nèi)聯(lián)(inline)杨蛋,那么編譯器在編譯代碼的時(shí)候就已經(jīng)知道程序中有printHello和printGoodbye這兩個(gè)函數(shù)了兜材,于是會直接生成調(diào)用這些函數(shù)的指令。而函數(shù)地址實(shí)際上是硬編碼在指令之中的逞力。若是將剛才那段代碼寫成下面這樣曙寡,就得使用“動態(tài)綁定”了。

圖2

編譯器在這種情況下生成的指令和圖1中的不同寇荧。

在OC中如果向某個(gè)對象傳遞消息卵皂,那就會使用動態(tài)綁定機(jī)制來決定需要調(diào)用的方法。在底層砚亭,所有方法都是普通的C函數(shù)灯变,然而對象受到消息之后,究竟該調(diào)用哪個(gè)方法則完全在運(yùn)行期決定捅膘,甚至可以在程序運(yùn)行時(shí)改變添祸,這些特性使得OC成為了一門真正的動態(tài)語言。

在OC中給對象發(fā)送消息可以這樣來寫:

圖3

someObj是接收者(receiver)寻仗,messageName叫做選擇子(selector)刃泌,選擇子和參數(shù)合起來稱為“消息(message)”。編譯器看到此消息后署尤,將其轉(zhuǎn)換為一條標(biāo)準(zhǔn)的C語言函數(shù)調(diào)用耙替,所調(diào)用的函數(shù)乃是消息傳遞機(jī)制中的核心函數(shù),叫做objc_msgSend曹体,其原型如下:

圖4

這是個(gè)參數(shù)可變的函數(shù)俗扇,能接受兩個(gè)和兩個(gè)以上的參數(shù),第一個(gè)參數(shù)代表接收者箕别,第二個(gè)參數(shù)是選擇子(SEL是選擇子的類型)铜幽,后續(xù)的參數(shù)就是消息中的那些參數(shù),其順序不變串稀。編譯器會把圖3中的消息轉(zhuǎn)換成如下函數(shù):

圖5

objc_msgSend函數(shù)會依據(jù)接收者與選擇子的類型來調(diào)用適當(dāng)?shù)姆椒ǔ住榱送瓿纱瞬僮鳎摲椒ㄐ枰诮邮照咚鶎俚念愔兴褜て洹胺椒斜怼蹦附兀绻苷业脚c選擇子名稱相符的方法到忽,就調(diào)至其實(shí)現(xiàn)代碼。如果找不到就沿著繼承體系繼續(xù)向上查找清寇,等找到合適的方法之后再跳轉(zhuǎn)喘漏。如果最終都找不到,那就執(zhí)行“消息轉(zhuǎn)發(fā)”操作颗管。

當(dāng)找到相符的方法之后陷遮,objc_msgSend會將匹配結(jié)果緩存在“快速映射表”里,每個(gè)類都會有這么一塊緩存垦江,如果稍后還向該類發(fā)送此消息帽馋,那么執(zhí)行起來就會很快了。

上面所敘述的只是部分消息的調(diào)用過程比吭,其實(shí)還有一些其他的“邊界情況”绽族,這時(shí)候需要交由OC運(yùn)行環(huán)境中的另外一些函數(shù)來處理:

1、objc_msgSend_stret:如果待發(fā)送的消息要返回結(jié)構(gòu)體衩藤,那么可交由此函數(shù)處理吧慢。只有當(dāng)CPU的寄存器能夠容納得下消息返回類型時(shí),這個(gè)函數(shù)才能處理此消息赏表。假如無法容納的時(shí)候(比如結(jié)構(gòu)體太大),那么由另一個(gè)函數(shù)執(zhí)行派發(fā)检诗。此時(shí)匈仗,那個(gè)函數(shù)會通過分配在棧上的某個(gè)變量來處理消息所返回的結(jié)構(gòu)體。

2逢慌、objc_msgSend_fpret:如果消息返回的是浮點(diǎn)數(shù)....悠轩。書上說這個(gè)函數(shù)是為了處理x86等架構(gòu)CPU中某些令人稍覺驚訝的奇怪狀況。

3攻泼、objc_msgSendSuper:給超類發(fā)消息火架,如[super message:paramater],那么就需要此函數(shù)來處理

猜測:stret->struct return忙菠、fpret->float point return

剛才提到何鸡,objc_msgSend等函數(shù)一旦找到應(yīng)該調(diào)用的方法實(shí)現(xiàn)之后,就會“跳轉(zhuǎn)過去”牛欢。之所以能這樣做骡男,是因?yàn)镺C對象的每個(gè)方法可以視為簡單的C函數(shù),其原型如下:

圖6

注:書中說“真正的函數(shù)名和上面寫的可能不太一樣氢惋,筆者用類(Class)和選擇子(selector)來命名是想解釋其工作原理”

每個(gè)類都有一張表格洞翩,表格里面存的都是指針,每個(gè)指針都會指向這種函數(shù)焰望,而選擇子的名稱則是查表時(shí)候所使用的“鍵”骚亿。objc_messageSend等函數(shù)正是通過這張表格來尋找應(yīng)該執(zhí)行的方法并跳轉(zhuǎn)到其實(shí)現(xiàn)的。圖6中原型的樣子和objc_messageSend很像熊赖,這不是巧合来屠,而且為了利用“尾調(diào)用優(yōu)化”技術(shù),令“跳轉(zhuǎn)到方法的實(shí)現(xiàn)”更加簡單一些震鹉。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末俱笛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子传趾,更是在濱河造成了極大的恐慌迎膜,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浆兰,死亡現(xiàn)場離奇詭異磕仅,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)簸呈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門榕订,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蜕便,你說我怎么就攤上這事劫恒。” “怎么了轿腺?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵两嘴,是天一觀的道長丛楚。 經(jīng)常有香客問我,道長憔辫,這世上最難降的妖魔是什么鸯檬? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮螺垢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赖歌。我一直安慰自己枉圃,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布庐冯。 她就那樣靜靜地躺著孽亲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪展父。 梳的紋絲不亂的頭發(fā)上返劲,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機(jī)與錄音栖茉,去河邊找鬼篮绿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛吕漂,可吹牛的內(nèi)容都是我干的亲配。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼惶凝,長吁一口氣:“原來是場噩夢啊……” “哼吼虎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起苍鲜,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤思灰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后混滔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體洒疚,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年遍坟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拳亿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡愿伴,死狀恐怖肺魁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情隔节,我是刑警寧澤鹅经,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布寂呛,位于F島的核電站,受9級特大地震影響瘾晃,放射性物質(zhì)發(fā)生泄漏贷痪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一蹦误、第九天 我趴在偏房一處隱蔽的房頂上張望劫拢。 院中可真熱鬧,春花似錦强胰、人聲如沸舱沧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽熟吏。三九已至,卻和暖如春玄窝,著一層夾襖步出監(jiān)牢的瞬間牵寺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工恩脂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留帽氓,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓东亦,卻偏偏與公主長得像杏节,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子典阵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

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