Runtime(一)消息傳遞機(jī)制

Introduction

The Objective-C language defers as many decisions as it can from compile time and link time to runtime. Whenever possible, it does things dynamically. This means that the language requires not just a compiler, but also a runtime system to execute the compiled code.

OC是一種面向?qū)ο蟮膭?dòng)態(tài)語(yǔ)言,動(dòng)態(tài)語(yǔ)言就是在運(yùn)行時(shí)來(lái)執(zhí)行靜態(tài)語(yǔ)言的編譯鏈接的工作。這就要求除了編譯器之外還要有一種運(yùn)行時(shí)系統(tǒng)來(lái)執(zhí)行編譯等功能。OC中這個(gè)系統(tǒng)就是runtime。

  • 編譯時(shí)間指編譯程序?qū)⒃闯绦蚓幾g成目標(biāo)程序所占用的時(shí)間。
  • 源程序,是指未經(jīng)編譯的,按照一定的程序設(shè)計(jì)語(yǔ)言規(guī)范書寫的,人類可讀的文本文件。通常由高級(jí)語(yǔ)言編寫。
  • 目標(biāo)程序,又稱為“目的程序”,為源程序經(jīng)編譯可直接被計(jì)算機(jī)運(yùn)行的機(jī)器碼集合,在計(jì)算機(jī)文件上以.obj作擴(kuò)展名。目標(biāo)代碼盡管已經(jīng)是機(jī)器指令,但是還不能運(yùn)行,因?yàn)槟繕?biāo)程序還沒(méi)有解決函數(shù)調(diào)用問(wèn)題,需要將各個(gè)目標(biāo)程序與庫(kù)函數(shù)連接,才能形成完整的可執(zhí)行程序。

Messaging

這一章描述了:

  • 消息表達(dá)式(message expression)如何轉(zhuǎn)換為objc_msgSend函數(shù)調(diào)用。
  • 如何通過(guò)名稱(name)來(lái)引用方法(methods)。
  • 說(shuō)明如何充分利用objc_msgSend。
  • 如何規(guī)避(circumvent)動(dòng)態(tài)綁定(dynamic binding)。

The objc_msgSend Function

[receiver message]

在OC中,消息(message)在運(yùn)行時(shí)(runtime)才被綁定到方法實(shí)現(xiàn)。編譯器(compiler)把消息轉(zhuǎn)換(convert to)為函數(shù)objc_msgSend的調(diào)用。objc_msgSend將接收方(receiver)和消息中提到的方法的名稱(即selector)作為函數(shù)的兩個(gè)重要的參數(shù):

objc_msgSend(receiver, selector)

消息中所有參數(shù)(arguments)也會(huì)傳遞給objc_msgSend函數(shù):

objc_msgSend(receiver, selector, arg1, arg2, ...)

objc_msgSend為動(dòng)態(tài)綁定執(zhí)行所需的一切。

  • 首先,它查找selector引用的實(shí)現(xiàn)方法。(因?yàn)橄嗤姆椒梢员徊煌念悓?shí)現(xiàn),所以定位精確的實(shí)現(xiàn)方法取決于receiver的的類型)
  • 然后,調(diào)用實(shí)現(xiàn)方法,把receiver和方法指定的參數(shù)傳遞給它。
  • 最后,把實(shí)現(xiàn)方法的返回值作為它的返回值。

note:編譯器生成對(duì)objc_msgSend的調(diào)用,你不要直接在代碼中直接調(diào)用它

消息傳遞的關(guān)鍵依賴于編譯器為每個(gè)類和對(duì)象創(chuàng)建的結(jié)構(gòu)(structures),每個(gè)類結(jié)構(gòu)包含兩個(gè)基本(essential)元素:

  • 一個(gè)指向父類的指針(A point to the superclass)
  • 一個(gè)類的調(diào)度表(A class dispatch table)。這個(gè)表?yè)碛袑⒎椒ㄟx擇器(method selector)與特定類的方法地址相關(guān)聯(lián)的條目(entries)。例如:setOrigin::的selector與setOrigin::的實(shí)現(xiàn)方法(implementation)地址關(guān)聯(lián)起來(lái)。

當(dāng)創(chuàng)建一個(gè)新對(duì)象時(shí),內(nèi)存會(huì)為它分配空間,并且它的實(shí)例變量會(huì)被初始化。這個(gè)對(duì)象的所有變量中第一個(gè)是isa指針(指向它的類structure),object可以根據(jù)isa訪問(wèn)它的類和父類。


當(dāng)一個(gè)objc_msgSend發(fā)送給一個(gè)對(duì)象時(shí),沿著isa查找類結(jié)構(gòu)中調(diào)度表(dispatch table)中的selector對(duì)應(yīng)的實(shí)現(xiàn)方法的地址(address)。如果沒(méi)有找到對(duì)應(yīng)的selector,則繼續(xù)沿著isa查找父類的dispatch table的selector。連續(xù)的失?。╯uccessive failures)導(dǎo)致objc_msgSend遍歷層級(jí),直到遍歷到NSObject。

為了加快消息傳遞速度,runtime系統(tǒng)會(huì)緩沖(cache)已經(jīng)使用過(guò)的selectors和addresses of methods。每一個(gè)類都單獨(dú)(seperate)創(chuàng)建cache緩沖繼承(inherited)的和定義的方法。

Using Hidden Arguments

當(dāng)objc_msgSend找到方法實(shí)現(xiàn)的地址,調(diào)用方法,并把message中的arguments傳遞給它。同時(shí),也包含兩個(gè)隱藏的(hidden)arguments。

  • 接受消息的對(duì)象(The receiving object)。
  • 方法的選擇器(The selector for the method)。

這兩個(gè)參數(shù)為方法實(shí)現(xiàn)提供了明確的信息:消息表達(dá)式的兩半(即[receiver message])。方法將receiving object引用為self,將selector引用為_(kāi)cmd。

Getting a Method Address

void (*setter)(id, SEL, BOOL);
int i;
setter = (void(*)(id, SEL, BOOL))[target methodForSelector:@selector(setFilled:)];
for (i = 0, i < 1000, i++) {
  setter(targetList(i), @selector(setFilled:), YES);
}

阻止動(dòng)態(tài)綁定的唯一方式:獲取方法的地址(addresss),直接調(diào)用它(如果它是一個(gè)函數(shù))。這種情況只適合在連續(xù)多次調(diào)用某個(gè)方法的時(shí)候,可以減少動(dòng)態(tài)綁定的消耗。

NSObject的methodForSelector:返回一個(gè)方法(method)的指針(pointer),用這個(gè)pointer去實(shí)現(xiàn)一個(gè)方。methodForSelector:返回的指針必須小心的轉(zhuǎn)換為正確的函數(shù)類型。返回和參數(shù)類型都應(yīng)該包含在轉(zhuǎn)換中。例如:

void (*setter)(id, SEL, BOOL);
int i;
setter = (void(*)(id, SEL, BOOL))[target methodForSelector:@selector(setFilled:)];

接受對(duì)象(receiving object)和方法選擇器(method selecotr),這兩個(gè)參數(shù)(arguments)在方法語(yǔ)法中(method syntax)中是被隱藏的,但是方法作為函數(shù)(function)調(diào)用時(shí),必須是顯示的(explicit)。例如:

setter(targetList(i), @selector(setFilled:), YES);

使用methodForSelector:阻止動(dòng)態(tài)綁定在消息傳遞中節(jié)省了大部分時(shí)間,但是這大部分時(shí)間只有在以下情況才有意義:某個(gè)確定的方法連續(xù)的調(diào)用。如在for loop。

note:methodForSelector:由Cocoa runtime system提供,不是Objective-C語(yǔ)言的特定。

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

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,030評(píng)論 0 9
  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,872評(píng)論 33 466
  • 參考鏈接: http://www.cnblogs.com/ioshe/p/5489086.html 簡(jiǎn)介 Runt...
    樂(lè)樂(lè)的簡(jiǎn)書閱讀 2,240評(píng)論 0 9
  • 轉(zhuǎn)載:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麥子閱讀 827評(píng)論 0 2
  • 本文轉(zhuǎn)載自:http://yulingtianxia.com/blog/2014/11/05/objective-...
    ant_flex閱讀 867評(píng)論 0 1

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