msgSend 流程詳解

2021-09-23 22:50:14 字數 1597 閱讀 7380

1.編譯階段

使用者呼叫乙個普通函式

[anobject dotings:things];

編譯器會把其編譯為:

objc_msgsend(anobject, @selector(dothings:), things);

注意:根據函式返回值的不同,編譯器還會將其編譯為objc_msgsend_stret、objc_msgsend_fpret等。但是,實現大同小異。這裡只以objc_msgsend為例進行討論。

2.msgsend概述

objc_msgsend實現大致如下:

id objc_msgsend(id self, sel _cmd, ...)

return imp ? imp(self, _cmd, ...) : 0

}

由此可見,其主要功能可分為獲取函式imp和呼叫imp兩塊。

3.msgsend整體流程

step1. dispatch table中搜尋selector的imp。這步大家應該都清楚,子類找不到,就去搜尋父類,依次往上遍歷。

注:dispatch table是編譯時生成的selector與imp的對應表

step2. 如果子類和所有父類的dispatch table中都沒找到,就到動態解析。

很多人可能認為,這個曲折的尋找過程是必不可少的。其實並不是這樣的。可以將子類中某個方法的imp直接設定成objc_msgforward,就可以直接進入**流程。

step3.函式呼叫

這裡著重介紹下**機制(__forwarding__)的實現。其**大致如下:

這裡不做詳細分析,簡要說下我認為有用的幾點:

a.為何有了forwardingin***ction,還需要fowardingtarget?

因為fowardingtarget不涉及引數解析與封裝,只是簡單的把target替換下,就立馬進入下一輪msgsend,所以效率較高,是首選。只有當涉及引數處理時,才有必要在forwardingin***ction中乾。

b.為什麼forwardingin***ction前,需要獲取methodsignature?

單靠selector,無法完成對引數的解析,從而無法完成對target、selector和引數的打包。此時,需要獲取method signature(包含引數、返回值的所有資訊)來協助完成對引數的解析。

objc_msgforward和其他函式imp一樣,都是函式指標

objc_msgforward和其他函式imp一樣,都是函式指標

objc_msgforward和其他函式imp一樣,都是函式指標

重要的事情說三遍

參考文獻

[1] what's that selector?

[2] effective objective-c 2.0:編寫高質量ios與os x**的52個有效方法

測試流程詳解

首先回顧一下,軟體測試的生命週期 需求分析 測試計畫 測試設計 測試開發 測試執行 測試評估 然後開始今天的講解,測試流程 需求分析 測試計畫 編寫測試用例 測試執行 測試報告編寫 準備工作 確定測試範圍 一般情況,50 的錯誤都來自於需求。分析方法 確定整個專案測試的把控 測試計畫包括 根據測試計...

Spring Security流程詳解

授權 authorization 由spring 根據spring security.xml 建立spring security的物件,並把它們交給spring容器管理 當乙個請求過來,首先經過 delegatingfilterproxy 過濾器 由它將請求交給spring security 內部的...

xenpaging流程詳解

1 xenpaging初始化。2 交換檔案初始化。3 訊號處理初始化。4 建立page in執行緒。5 將記憶體頁page out到交換檔案上。程式中,通過for迴圈呼叫evict victim函式將數量為num pages的頁從虛擬機器中page out出來。當找不到num pages個滿足pag...