內(nèi)容來(lái)源:https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtHowMessagingWorks.html
The objc_msgSend Function
在objective-C里,在運(yùn)行時(shí)前,消息并不和方法實(shí)現(xiàn)綁定.也就是說(shuō),在運(yùn)行前只知道方法名,并不知道方法具體實(shí)現(xiàn)(方法體).
編繹器會(huì)把
[receiver message]
轉(zhuǎn)成
objc_msgSend(receiver, selector)
如果有參數(shù)
objc_msgSend(receiver, selector, arg1, arg2, ...)
這個(gè)消息方法做以下的動(dòng)態(tài)綁定:
1.這會(huì)先找到這個(gè)selector所對(duì)應(yīng)的方法實(shí)現(xiàn)(方法體).
2.它會(huì)把接收方法的對(duì)象以及所有參數(shù)傳入方法實(shí)現(xiàn).
3.最后,它把程序的最后的計(jì)算結(jié)果,作回return 值傳回.
注意:編譯器會(huì)生成消息傳遞方法(objc_msgSend),你自己決不能直接調(diào)用.
每一個(gè)類結(jié)構(gòu)(class structure)包含兩部分:
1:一個(gè)指向你類的指針.
2:一個(gè)類 分配表(dispatch table).這個(gè)表,應(yīng)該是鍵值對(duì)應(yīng)關(guān)系,鍵是方法selector,值是方法具體實(shí)現(xiàn)的地址.通過(guò)個(gè)地址可以找到方法體.
當(dāng)一個(gè)新對(duì)象創(chuàng)建時(shí),內(nèi)存會(huì)被分配,并且它的實(shí)例亦是也會(huì)被初始化.第一個(gè)對(duì)象變量是指向?qū)λ惤Y(jié)構(gòu)(class structure)的指針.這個(gè)指針被叫作 "isa",讓對(duì)象能訪問(wèn)它的類,通過(guò)類,能訪問(wèn)所有它繼承的類.
"isa" 是struct objc_object類型的指針
方法的層級(jí)調(diào)用,
當(dāng)一個(gè)方法傳給對(duì)象,對(duì)象會(huì)通知道isa找到類結(jié)構(gòu),類結(jié)構(gòu)里有dispatch table,在table里找selector,如果沒(méi)找到,會(huì)找父類的dispatch table.直到找到或到達(dá)NSObject.一旦找到方法就會(huì)調(diào)用,并傳入接收c對(duì)象的數(shù)據(jù)結(jié)構(gòu).
為了加快消息傳遞的進(jìn)程,每個(gè)類都有自己的緩存,它可以包含繼承的方法,就像這個(gè)方法是在本類里定義的一樣.在搜索dispatch table之間,會(huì)先檢查接收方法的類的方法緩存,如果有就直接調(diào)用,速度只比一個(gè)函數(shù)調(diào)用稍微慢一些.一旦一個(gè)工程運(yùn)行的足夠長(zhǎng),它所有的方法都在緩存里找到.緩存大小也會(huì)動(dòng)態(tài)的增加,以至于可以容納親的消息.
當(dāng)objc_msgSend找到方法的具體實(shí)現(xiàn),它會(huì)調(diào)用程序并傳入所有的參數(shù).這個(gè)包含兩個(gè)隱藏的參數(shù)
1:接收對(duì)象本身.
2:方法的selector