訊息傳遞(Messaging)

2021-06-28 01:55:42 字數 2455 閱讀 9702

本章描述了如何將訊息表示式轉換成objc_msgsend函式呼叫,以及如何通過名字引用方法。然後解釋如何利用objc_msgsend以及如何避免動態繫結

在objective-c中,直到執行時,訊息才會繫結到方法的實現。編譯器才會轉換訊息表示式,

[receiver message]
呼叫訊息傳遞行數objc_msgsend。這個函式需要接收者和訊息中提到的方法名即方法選擇器作為它的兩個主要引數:

objc_msgsend(receiver, selector)
訊息中傳入的任何引數都可以在objc_msgsend處理:

objc_msgsend(receiver, selector, arg1, arg2, ...)
訊息傳遞函式支援動態繫結:

注意:編譯器生成訊息傳遞函式。不能在**中直接呼叫。

訊息傳遞的關鍵在於編譯器編譯每個類和物件的結構。每個類結構包括這兩個基本要素:

當建立乙個新物件,會分配記憶體並初始化例項變數。首先,物件變數是乙個指向類結構的指標。該指標,稱為isa,通過類,物件可以訪問該類和該物件繼承的所有類。

注意:isa指標雖然不是語言嚴格意義上的一部分,但是是使用objective-c執行時系統所需的乙個物件。乙個物件須「等效於」結構定義中的struct objc_object(定義於objc/objc.h)。然而,很少需要建立自己的根物件和繼承自nsobject 或nsproxy 的物件,自動有isa變數。

類元素和物件結構如圖3-1所示。

圖3-1 訊息傳遞框架

當乙個訊息傳送到乙個物件,訊息傳遞函式遵循物件的isa指標,該指標指向類結構,並在dispatch表中查詢方法選擇器。如果不能找到選擇器,objc_msgsend則遵循指向父類的指標並試圖在dispatch表找到選擇器。一直找不到選擇器,objc_msgsend將一直查詢類的層次結構,直到nsobject類。一旦定位到選擇器,函式將呼叫表中的方法,並將其傳遞到接收物件的資料結構。

執行時選擇以這種方式實現方法。或者以物件導向程式設計術語來說,該方法是動態繫結到訊息。

為了加快訊息傳遞過程,執行時系統快取使用的方法的選擇器和位址。每個類有乙個單獨的快取,可以包含繼承方法和類中定義方法的選擇器。在搜尋dispatch表之前,訊息傳遞程式首先檢查接收物件類(理論上,是有可能再次使用的方法)的快取。如果方法選擇器在快取中,訊息傳遞稍微比函式呼叫慢。一旦乙個程式執行足夠長時間來「熱身」快取,幾乎所有傳送的訊息都能找到快取方法。在程式執行時,快取能動態適應新訊息。

當objc_msgsend發現實現方法的程式,它呼叫程式,並傳遞訊息中所有的引數。也傳遞兩個隱藏引數到程式:

這些引數為每個方法實現提供明確資訊,這些資訊關於呼叫它們的訊息表示式。它們被認為是「隱藏」的,因為方法定義**中未宣告它們。當編譯**時,它們插入到實現中。

儘管這些引數沒有顯式的宣告,源**仍然可以引用它們(就像它可以引用接收物件的例項變數)。方法引用接收物件作為self,以及自己的選擇器作為_cmd。在下面的例子中,_cmd引用strange 方法的選擇器,self引用接收乙個strange 訊息的物件。

- strange

self對兩個引數更加有用。實際上,接收物件的例項變數可用於方法定義。

避免動態繫結的唯一方法是獲取方法的位址並且直接呼叫它,就好像它是個函式。當乙個特定的方法多次連續執行,並且你希望每次執行該方法時避免訊息傳遞開銷,在這種極少數的情況下,該方法可行。

nsobject類中定義乙個methodforselector:方法,可以訪問指向實現方法程式的指標,然後使用指標呼叫該程式。methodforselector:指標的返回值必須指向合適的函式型別。必須包含返回值和引數型別。

下面的例子展示了程式如何實現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);

前兩個引數傳遞給接收物件(self)的程式和方法選擇器(_cmd)。這些引數在方法語法中是隱藏的,但當該方法當成函式呼叫時,必須是顯式的。

使用methodforselector:方法避免動態繫結節省了訊息**所需的大部分時間。然而,只有在特定訊息重複多次的情況下,如上面的for迴圈,節省時間才會有重要意義。

注意:cocoa執行時系統提供methodforselector:方法,該方法並不是objective-c 語言本身的特性。

Android訊息傳遞之元件間傳遞訊息

前言 上篇學習總結了android通過handler訊息機制實現了工作執行緒與ui執行緒之間的通訊,今天來學習一下如何實現元件之間的通訊。本文依然是為學習eventbus做鋪墊,有對比才能進步,今天主要介紹在eventbus出現之前的實現方式,通過intent方式這裡不做介紹。需求場景 方式一 通過...

mfc 訊息傳遞

訊息分類 windows的訊息都是以wm 為名,wm 的意思是 windows message mfc把訊息分為三大類 命令訊息 wm command 命令訊息意味著 使用者命令程式做某些操作 凡是ui物件產生的訊息都是這種命令訊息,可能來自選單或加速鍵或工具欄按鈕,並且都以wm command呈現...

Intent 訊息傳遞

android為了遮蔽程序的概念,利用不同的元件 activity service 來表示程序之間的通訊!元件間通訊的核心機制是intent,通過intent可以開啟乙個activity或service,不論這個activity或service是屬於當前應用還是其它應用的!一 intent概念 in...