靜態繫結,即在編譯時就直接將要呼叫函式的位址寫進去,醬紫就直接進入呼叫函式中,如下**中,編譯器在編譯的時候就已經知道程式中有printhello與printgoodbye兩個函式,遇事會直接生成呼叫這些函式的指令。
#import void printhello()
void printgoodbye()
void dothething(int type) else
return
0;}
動態繫結,即要呼叫的函式直到執行時才能夠確定。如下**,編譯器在這種情況下生成的指令與剛才那個例子不同,在第乙個例子中,if與else語句裡都有函式呼叫指令。而在第二個例子中,只有乙個函式呼叫指令,不過帶呼叫的函式位址無法硬編碼在指令中,而是要在執行期讀取出來。
#import
void printhello()
void printgoodbye()
void dothething(int type) else
func();
return
0;}
在objective-c中,如果給某物件傳遞訊息,那就會使用動態繫結機制來決定需要呼叫的方法。如下例所示,someobject叫做receiver,messagename叫做slector,選擇子與引數合起來成為「訊息」。編譯器會將訊息轉換為訊息傳遞機制中得核心函式:objc_msgsend()。
//給物件傳送訊息
id returnvalue = [someobject messagename:parameter];
//編譯器會轉換成為
id returnvalue = objec_msgsend(someobject, @selector(messagename), parameter);
objc_msgsend()會按照如下流程處理訊息,期間做了些許優化處理
訊息傳遞機制圖
訊息**機制分為兩個階段。
物件在收到無法解讀的訊息後,首先將呼叫其所屬類的下列類方法:
+(bool)resolveinstancemethod:(sel)selector
使用這種方法的前提是:相關方法的實現**已經寫好了,只等著執行的時候動態插入在類裡面就可以了。此方案長用來實現@dynamic屬性1。
當前接受者還有第二次機會能處理未知的選擇子,在這一步中,執行期的系統會問它,能不能把這條訊息轉給其他接受者來處理。
-(id) forwardingtargetforselector:(sel)selector
在乙個物件內部,可能還有一些列其他物件,該物件可經由此方法將能夠處理某選擇子的相關內部物件返回。如果沒有則返回nil。
如果**演算法已經來到這一步的話,那麼唯一能做的就是啟用完整的訊息**機制了。首先建立nsinvocation物件,把與尚未處理的那條訊息有關的全部細節都封於其中。此物件包括選擇子、目標及引數。在觸發nsinvocation物件時,會呼叫下列方法
-(void)forwardinvocation:(nsinvocation*)invocation
實現此方法時,若發現某呼叫操作不應由本類處理,則需呼叫超類的同名方法。這樣子的話,繼承體系中得某個類都有機會處理此呼叫請求,直至nsobject。如果最後呼叫了nsobject類的方法,那麼該方法還會繼而當呼叫「doesnotrecognizeselector:」以丟擲異常,此異常表明選擇子最終未能得到處理。
有關訊息機制更詳細的文章:
↩
IOS訊息分發(廣播)機制
在ios中,提供了通知機制 notification 可以在物件間傳遞和接受資訊。傳遞和接受資訊的物件間甚至不需要知道對方的存在。究其本質來說,其實是設計模式中的觀察者模式的應用。一種更好的方式,就是使用ios中的notification機制。notification由三部分組成 傳送訊息者 訊息中...
iOS訊息機制基於廣播模型
ios訊息機制基於廣播模型 訊息中心 nsnotificationcenter 是基於程序的單件例項 訊息佇列 nsnotificationqueue 是基於執行緒的,每個執行緒都有乙個預設的訊息佇列,這個佇列相關聯於訊息中心,每個訊息中心或執行緒可以關聯於多個佇列。訊息中心是採用同步方式 訊息佇列...
ios的訊息機制 以及 動態性質
大部分的語言 使用的是 靜態繫結的函式呼叫方式。這種方式 在編譯階段就確定了執行時候需要呼叫的函式。而objective c 使用的是訊息傳遞機制。在執行的時候才會知道呼叫的函式。實際上 底層都是c語言的。而c語言是函式呼叫方式。那麼 objectie c的訊息響應機制是真麼實現的呢。其實 oc 中...