標籤:
本系列主要參考資料:
Objective-C Runtime Reference
Objective-C Runtime Programming Guide
涉及主要檔案:objc/message.h,objc/objc-api.h,objc/objc.h,objc/runtime.h
特酷吧[tekuba.net]採用"署名-非商業用途-保持一致"的創作共用協議,使用本文內容請遵循該協議
Objective-C Runtime是Objective-C的基礎內容,理解了Objective-C Runtime對於掌握Objective-C的很多技術原理非常有用。特酷吧特別整理了Objective-C Runtime的內容,共六篇,本文是第三篇:
《Objective-C Runtime分析(一)-Runtime初步》
《Objective-C Runtime分析(二)-Class,Method,SEL,IMP》
《Objective-C Runtime分析(三)-objc_msgSend》
《Objective-C Runtime分析(四)--Dynamic Method Resolution》
《Objective-C Runtime分析(五)-Message Forwarding》
《Objective-C Runtime分析(六)-Type Encodings & Declared Properties》
本部分主要參考:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtHowMessagingWorks.html#//apple_ref/doc/uid/TP40008048-CH104-SW1
通過前兩篇的學習,相信你已經對Objective-C Runtime有個一些瞭解,下面我們就該學習Objective-C Runtime中很重要的“訊息”了。
一,obj_msgSend
情景:
Tekuba *tekuba = [[Tekuba alloc] init];
[tekuba url];
執行[tekuba url]時,編譯器會自動的轉換成objc_msgSend(tekuba, @selector(url));
objc_msgSend的原型是:
id objc_msgSend(id theReceiver, SELtheSelector, ...)
參數分別是訊息接收對象,訊息對應的方法的標識SEL,以及參數。
在執行objc_msgSend方法時,主要完成了以下幾個工作:
The messaging function does everything necessary for dynamic binding:
(1),It first finds the procedure (method implementation) that the selector refers to. Since the same method can be implemented differently by separate classes, the precise procedure that it finds depends on the class of the receiver.
它首先找到 SEL 對應的方法實現 IMP。因為不同的類對同一方法可能會有不同的實現,所以找到的方法實現依賴於訊息接收者的類型。
(2),It then calls the procedure, passing it the receiving object (a pointer to its data), along with any arguments that were specified for the method.
然後將訊息接收者對象(指向訊息接收者對象的指標)以及方法中指定的參數傳遞給方法實現 IMP。
(3),Finally, it passes on the return value of the procedure as its own return value.
最後,將方法實現的傳回值作為該函數的傳回值返回。
NOTE:The compiler generates calls to the messaging function. You should never call it directly in the code you write.
二,隱藏參數
When objc_msgSend finds the procedure that implements a method, it calls the procedure and passes it all the arguments in the message. It also passes the procedure two hidden arguments:
(1)The receiving object
(2)The selector for the method
These arguments give every method implementation explicit information about the two halves of the message expression that invoked it. They’re said to be “hidden” because they aren’t declared in the source code that defines the method. They’re inserted into the implementation when the code is compiled.
當objc_msgSend找到方法對應的實現時,它將直接調用該方法實現,並將訊息中所有的參數都傳遞給方法實現,同時,它還將傳遞兩個隱藏的參數:(1)訊息的接收者;(2)方法名稱 SEL。這些參數協助方法實現獲得了訊息運算式的資訊。它們被認為是"隱藏"的是因為它們並沒有在定義方法的原始碼中聲明,而是在代碼編譯時間是插入方法的實現中的。
儘管這些參數沒有被顯示聲明,但在原始碼中仍然可以引用它們。在方法中可以通過self來引用訊息接收者對象,通過選標_cmd來引用方法本身。在下面的例子中,_cmd 指的是strange方法,self指的收到strange訊息的對象。
摺疊展開C/C++ Code複製內容到剪貼簿
- - strange
- {
- id target = getTheReceiver();
- SEL method = getTheMethod();
- if (target == self || mothod == _cmd)
- return nil;
- return [target performSelector:method];
- }
在這兩個參數中,self更有用一些。實際上,它是在方法實現中訪問訊息接收者對象的執行個體變數的途徑。
三,擷取方法地址
NSObject 類中的methodForSelector方法可以擷取指向方法實現IMP的指標,methodForSelectorL返回的指標和賦值的變數類型必須完全一致,包括方法的參數類型和傳回值類型。
下面的例子展示了怎麼使用指標來調用setFilled:的方法實現:
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);
The first two arguments passed to the procedure are the receiving object (self) and the method selector (_cmd). These arguments are hidden in method syntax but must be made explicit when the method is called as a function.
Using methodForSelector: to circumvent dynamic binding saves most of the time required by messaging. However, the savings will be significant only where a particular message is repeated many times, as in the for loop shown above.
Note that methodForSelector: is provided by the Cocoa runtime system; it‘s not a feature of the Objective-C language itself.
使用methodForSelector來避免動態綁定將減少大部分訊息的開銷,但是這隻有在指定的訊息被重複發送很多次時才有意義,例如上面的for迴圈。 [特酷吧的理解就是在基於NSObject的對象中,都有一個Class屬性,維護了一個方法緩衝,當多次調用的時候,是從緩衝中找IMP,自然就比較快]。
注意,methodForSelector是Cocoa運行時系統的提供的功能,而不是Objective-C語言本身的功能。
轉載請註明來自特酷吧,本文地址:www.tekuba.net/program/338/
推薦閱讀:
IOS7運動視覺效果[UIInterpolatingMotionEffect]
IOS CoreAnimation核心動畫(1)-CALayer和CAAnimation初步
iOS下TTS語音合成的幾種方案
iOS 圖片平鋪和展開
iOS Quartz2D字型描邊加粗等
想及時擷取特酷吧的更新?想瞭解iOS,android開發最新技術動態,點擊或掃描下方二維碼下載“多識閱讀”App,豐富的iOS,Android,Web等領域開發人員部落格隨你訂閱。
《Objective-C Runtime分析(三)-objc_msgSend》