ios底層開發訊息機制(二)訊息調用過程

來源:互聯網
上載者:User

標籤:io   os   ar   使用   for   sp   strong   on   代碼   

上一章節對基礎概念有了些瞭解,我們對ObjC 中的訊息應該有個大致思路了:樣本

Bird * aBird = [[Bird alloc] init];

[aBird fly];

中對 fly 的調用,編譯器通過插入一些代碼,將之轉換為對方法具體實現IMP的調用,這個 IMP是通過在 Bird 的類結構中的方法鏈表中尋找名稱為fly 的 選標SEL 對應的具體方法實現找到的。

上面的思路還有一些沒有提及的話題,比如說編譯器插入了什麼代碼,如果在方法鏈表中沒有找到對應的 IMP又會如何,這些話題在下面展開。

訊息函數 obj_msgSend:

編譯器會將訊息轉換為對訊息函數 objc_msgSend的調用,該函數有兩個主要的參數:訊息接收者id 和訊息對應的方法選標 SEL, 同時接收訊息中的任意參數:

id objc_msgSend(id theReceiver, SELtheSelector, ...)

如上面的訊息 [aBird fly]會被轉換為如下形式的函數調用:

objc_msgSend(aBird, @selector(fly));

該訊息函數做了動態綁定所需要的一切工作:

1,它首先找到 SEL 對應的方法實現 IMP。因為不同的類對同一方法可能會有不同的實現,所以找到的方法實現依賴於訊息接收者的類型。
2, 然後將訊息接收者對象(指向訊息接收者對象的指標)以及方法中指定的參數傳遞給方法實現 IMP。
3, 最後,將方法實現的傳回值作為該函數的傳回值返回。

 

編譯器會自動插入調用該訊息函數objc_msgSend的代碼,我們無須在代碼中顯示調用該訊息函數。當objc_msgSend找到方法對應的實現時,它將直接調用該方法實現,並將訊息中所有的參數都傳遞給方法實現,同時,它還將傳遞兩個隱藏的參數:訊息的接收者以及方法名稱 SEL。這些參數協助方法實現獲得了訊息運算式的資訊。它們被認為是”隱藏“的是因為它們並沒有在定義方法的原始碼中聲明,而是在代碼編譯時間是插入方法的實現中的。

儘管這些參數沒有被顯示聲明,但在原始碼中仍然可以引用它們(就象可以引用訊息接收者對象的執行個體變數一樣)。在方法中可以通過self來引用訊息接收者對象,通過選標_cmd來引用方法本身。在下面的例子中,_cmd 指的是strange方法,self指的收到strange訊息的對象。

 

- strange

{

    id target = getTheReceiver();

    SEL method = getTheMethod();

 

    if (target == self || mothod == _cmd)

        return nil;

 

    return [target performSelector:method];

}

在這兩個參數中,self更有用一些。實際上,它是在方法實現中訪問訊息接收者對象的執行個體變數的途徑。

尋找 IMP 的過程:

前面說了,objc_msgSend 會根據方法選標 SEL 在類結構的方法列表中尋找方法實現IMP。這裡頭有一些文章,我們在前面的類結構中也看到有一個叫objc_cache *cache 的成員,這個緩衝為提高效率而存在的。每個類都有一個獨立的緩衝,同時包括繼承的方法和在該類中定義的方法。。

 

尋找IMP 時:

1,首先去該類的方法 cache 中尋找,如果找到了就返回它;

2,如果沒有找到,就去該類的方法列表中尋找。如果在該類的方法列表中找到了,則將 IMP 返回,並將它加入cache中緩衝起來。根據最近使用原則,這個方法再次調用的可能性很大,緩衝起來可以節省下次調用再次尋找的開銷。3,3,如果在該類的方法列表中沒找到對應的 IMP,在通過該類結構中的 super_class指標在其父類結構的方法列表中去尋找,直到在某個父類的方法列表中找到對應的IMP,返回它,並加入cache中。

4,如果在自身以及所有父類的方法列表中都沒有找到對應的 IMP,則進入下文中要講的訊息轉寄流程。

 

便利函數:

我們可以通過NSObject的一些方法擷取運行時資訊或動態執行一些訊息:

 class   返回對象的類;

 isKindOfClass 和 isMemberOfClass檢查對象是否在指定的類繼承體系中;

 respondsToSelector 檢查對象能否相應指定的訊息;

 conformsToProtocol 檢查對象是否實現了指定協議類的方法;

 methodForSelector  返回指定方法實現的地址。

 performSelector:withObject 執行SEL 所指代的方法。

ios底層開發訊息機制(二)訊息調用過程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.