編寫高質量OC程式碼52建議總結:11.理解objc_msgSend的作用(訊息機制)
在物件上呼叫方法,術語叫做“傳遞訊息”,訊息有“名稱”和“選擇器(方法)”,可以接收引數,還可能有返回值。OC是C的超集,C語言使用靜態繫結,在編譯期間就能決定執行時做呼叫的函式。
#include <stdio.h>
void printHello() {
printf("hello, world!\n");
}
void printGoodbye() {
printf("Goodbye, world!\n");
}
void doTheThing(int type) {
if (type == 0) {
printHello();
} else {
printGoodbye();
}
}
編譯器在編譯程式碼的時候就知道有printHello和printGoodbye兩個函式了,會直接生成呼叫這些函式的指令,函式地址實際上是硬編碼在指令之中。
#include <stdio.h>
void printHello() {
printf("hello, world!\n");
}
void printGoodbye() {
printf("Goodbye, world!\n");
}
void doTheThing(int type) {
void (*fnc)();
if (type == 0) {
fnc = printHello;
} else {
fnc = printGoodbye;
}
fnc();
}
如果程式碼變成這樣,就得使用“動態繫結”,因為所要呼叫的函式直到執行期才能確定,第一個例子中,if 和 else 中都有函式呼叫指令,第二個例子中只有一個函式呼叫指令,待呼叫的函式地址無法硬編碼在指令中,要在執行期讀取出來。
給物件傳送訊息可以這麼寫:
id returnValue = [someObject messageName:parameter];
someObject叫做“接受者”,messageName叫做“選擇器”,選擇器與引數合起來叫做“訊息”。編譯器將上述語句轉換為C語言函式呼叫 “objc_msgSend”
void objc_msgSend(id self, SEL cmd, ...)
這是個“引數個數可變的函式”,能接受兩個或兩個以上的引數。第一個引數代表接受者,第二個引數代表選擇器,後續引數是訊息中的引數編譯器會把剛才的例子轉換為如下函式。
id returnValue = objc_msgSend(someObject, @selector(messageName:), parameter);
objc_msgSend 會在接受者所屬的類中搜尋其“方法列表”,如果找到與“選擇器”名稱相符的程式碼就實現,沒找到就延繼承體系向上查詢,最終找不到,就實現“訊息轉發”。
備註:每個類都有一塊快取“快速對映表”,如果稍後還向該類傳送相同的訊息,執行就快。
執行環境中一些“邊界情況”,需要其他函式處理
1.objc_msgSend_stret:如果待傳送的訊息要返回結構體,交給這個函式。
2.objc_msgSend_fpre:如果訊息返回的是浮點數,交給這個函式。
3.objc_msgSendSuper:給超類發訊息,用這個函式。也有與objc_msgSend_fpre和objc_msgSend_fpre等效的處理超類訊息的方法。
OC物件的每個方法都可以看做簡單的C函式,原型如下:
<return_type> Class_selector(id self, SEL _cmd, ...)
每個類裡都會有一張表格,其中的指標都會指向這種函式,選擇器的名稱則是查表時用的“鍵”,objc_msgSend用這張表來尋找應該執行的方法並跳轉實現。“尾呼叫優化”:如果函式的最後一項操作是呼叫另外一個函式,編譯器會生成調轉至另一個函式所用的指令碼。不會向呼叫堆疊中推入新的“棧幀”。
注意:只有當函式的最後一項操作僅僅是呼叫其他函式而不會將其返回值另做他用時
相關文章
- 編寫高質量OC程式碼52建議總結:12.理解訊息轉發機制C程式
- 編寫高質量OC程式碼52建議總結:17.實現describtion方法C程式
- 編寫高質量OC程式碼52建議總結:16.提供“全能初始化方法”C程式
- 編寫高質量OC程式碼52建議總結:13.用“方法調配技術”除錯“黑盒方法”C程式除錯
- 編寫高質量程式碼:改善Java程式的151個建議(第4章:字串___建議52~55)Java字串
- [編寫高質量iOS程式碼的52個有效方法](九)塊(block)iOSBloC
- 我總結了寫出高質量程式碼的12條建議
- OC訊息機制,訊息轉發機制
- 編寫高質量iOS與OS X程式碼的52個有效方法(一)iOS
- 編寫高質量iOS與OS X程式碼的52個有效方法(五)iOS
- 編寫高質量iOS與OS X程式碼的52個有效方法(二)iOS
- 編寫高質量程式碼 改善Python程式的91個建議Python
- 編寫高質量iOS有效方法總結(一)iOS
- [編寫高質量iOS程式碼的52個有效方法](七)記憶體管理(上)iOS記憶體
- [編寫高質量iOS程式碼的52個有效方法](八)記憶體管理(下)iOS記憶體
- [編寫高質量iOS程式碼的52個有效方法](十)Grand Central Dispatch(GCD)iOSGC
- 怎樣編寫高質量的java程式碼Java
- 編寫高質量的程式碼,從命名入手
- 寫出高質量程式碼的10個建議
- 《編寫高質量程式碼:改善Java程式的151個建議》筆記Java筆記
- 如何編寫高質量的C#程式碼(一)C#
- iOS 編寫高質量Objective-C程式碼iOSObjectC程式
- [轉]高質量JAVA程式碼編寫規範Java
- 編寫高質量程式碼:改善Java程式的151個建議(第4章:字串___建議56~59)Java字串
- 書寫高質量sql的一些建議SQL
- JAVA優質程式碼編寫的30條可行建議Java
- 如何編寫高質量和可維護的程式碼
- [Unity 程式碼寫法整理]訊息機制(三)Unity
- 編寫高質量程式碼
- iOS 編寫高質量Objective-C程式碼(四)iOSObjectC程式
- iOS 編寫高質量Objective-C程式碼(一)iOSObjectC程式
- iOS 編寫高質量Objective-C程式碼(三)iOSObjectC程式
- iOS 編寫高質量Objective-C程式碼(二)iOSObjectC程式
- iOS 編寫高質量Objective-C程式碼(八)iOSObjectC程式
- iOS編寫高質量Objective-C程式碼(四)iOSObjectC程式
- iOS編寫高質量Objective-C程式碼(二)iOSObjectC程式
- iOS 編寫高質量Objective-C程式碼(五)iOSObjectC程式
- iOS 編寫高質量Objective-C程式碼(六)iOSObjectC程式