一、引言
[receiver message]不單單是簡(jiǎn)單的方法調(diào)用搓谆,其實(shí)它會(huì)被編譯器轉(zhuǎn)化為objc_msgSend(receiver, selector),如果編譯器能找到對(duì)應(yīng)的selector摆舟,那么就相當(dāng)于執(zhí)行了receiver這個(gè)對(duì)象的方法彤悔,否則摊求,消息要么被轉(zhuǎn)發(fā)禽拔,或是臨時(shí)向接收者動(dòng)態(tài)添加selector對(duì)應(yīng)的實(shí)現(xiàn)內(nèi)容,要么crash掉。
所以[receiver message]只是在編譯的時(shí)候決定發(fā)送message這條消息睹栖,具體還是要看運(yùn)行時(shí)的處理硫惕。
二、簡(jiǎn)介
OC語言是動(dòng)態(tài)語言野来,它總會(huì)把工作從編譯期推遲到運(yùn)行期恼除,其中就需要有編譯器和運(yùn)行時(shí)系統(tǒng)(runtime system)。
OC從三個(gè)層面上與runtime系統(tǒng)交互曼氛,一是通過OC源碼豁辉,二是通過Foundation框架的NSobject類定義的方法,三是對(duì)runtime函數(shù)的直接調(diào)用舀患。
大部分情況下你就只管寫你的Objc代碼就行徽级,runtime 系統(tǒng)自動(dòng)在幕后辛勤勞作著。
還記得引言中舉的例子吧聊浅,消息的執(zhí)行會(huì)使用到一些編譯器為實(shí)現(xiàn)動(dòng)態(tài)語言特性而創(chuàng)建的數(shù)據(jù)結(jié)構(gòu)和函數(shù)餐抢,Objc中的類、方法和協(xié)議等在 runtime 中都由一些數(shù)據(jù)結(jié)構(gòu)來定義狗超,這些內(nèi)容在后面會(huì)講到弹澎。(比如objc_msgSend函數(shù)及其參數(shù)列表中的id和SEL都是啥)
Cocoa 中大多數(shù)類都繼承于NSObject類,也就自然繼承了它的方法努咐。最特殊的例外是NSProxy,它是個(gè)抽象超類殴胧,它實(shí)現(xiàn)了一些消息轉(zhuǎn)發(fā)有關(guān)的方法渗稍,可以通過繼承它來實(shí)現(xiàn)一個(gè)其他類的替身類或是虛擬出一個(gè)不存在的類,說白了就是領(lǐng)導(dǎo)把自己展現(xiàn)給大家風(fēng)光無限团滥,但是把活兒都交給幕后小弟去干竿屹。
有的NSObject中的方法起到了抽象接口的作用,比如description方法需要你重載它并為你定義的類提供描述內(nèi)容灸姊。NSObject還有些方法能在運(yùn)行時(shí)獲得類的信息拱燃,并檢查一些特性,比如class返回對(duì)象的類力惯;isKindOfClass:和isMemberOfClass:則檢查對(duì)象是否在指定的類繼承體系中碗誉;respondsToSelector:檢查對(duì)象能否響應(yīng)指定的消息;conformsToProtocol:檢查對(duì)象是否實(shí)現(xiàn)了指定協(xié)議類的方法父晶;methodForSelector:則返回指定方法實(shí)現(xiàn)的地址哮缺。
Runtime 系統(tǒng)是一個(gè)由一系列函數(shù)和數(shù)據(jù)結(jié)構(gòu)組成,具有公共接口的動(dòng)態(tài)共享庫甲喝。頭文件存放于/usr/include/objc目錄下尝苇。許多函數(shù)允許你用純C代碼來重復(fù)實(shí)現(xiàn) Objc 中同樣的功能。雖然有一些方法構(gòu)成了NSObject類的基礎(chǔ),但是你在寫 Objc 代碼時(shí)一般不會(huì)直接用到這些函數(shù)的糠溜,除非是寫一些 Objc 與其他語言的橋接或是底層的debug工作淳玩。