1. 程式人生 > >runtime從入門到精通(五)—— 訊息傳送和訊息轉發

runtime從入門到精通(五)—— 訊息傳送和訊息轉發

前一篇文章中,我們介紹了runtime相關的術語的資料結構,檢視連結:runtime相關的術語的資料結構。本文主要講解與runtime相關的訊息傳送訊息轉發兩個重要模組。

訊息傳送

訊息傳送舉例:下面這個OC程式碼

[person read:book];

會被編譯成:

objc_msgSend(person, @selector(read:), book);

objc_msgSend的具體流程如下:

  1. 通過isa指標找到所屬類
  2. 查詢類的cache列表, 如果沒有則下一步
  3. 查詢類的”方法列表”
  4. 如果能找到與選擇子名稱相符的方法, 就跳至其實現程式碼
  5. 找不到, 就沿著繼承體系繼續向上查詢
  6. 如果能找到與選擇子名稱相符的方法, 就跳至其實現程式碼
  7. 找不到, 執行”訊息轉發”.

訊息轉發

上面我們提到, 如果到最後都找不到, 就會來到訊息轉發,訊息轉發的流程如下:

  1. 動態方法解析 : 先問接收者所屬的類, 你看能不能動態添加個方法來處理這個”未知的訊息”? 如果能, 則訊息轉發結束.
  2. 備胎(後備接收者) : 請接收者看看有沒有其他物件能處理這條訊息? 如果有, 則把訊息轉給那個物件, 訊息轉發結束.
  3. 訊息簽名 : 這裡會要求你返回一個訊息簽名, 如果返回nil, 則訊息轉發結束.
  4. 完整的訊息轉發 : 備胎都搞不定了, 那就只能把該訊息相關的所有細節都封裝到一個NSInvocation物件, 再問接收者一次, 快想辦法把這個搞定了. 到了這個地步如果還無法處理, 訊息轉發機制也無能為力了。

1. 動態方法解析

物件在收到無法解讀的訊息後, 首先呼叫其所屬類的這個類方法 :

+ (BOOL)resolveInstanceMethod:(SEL)selector
// selector : 那個未知的選擇子
// 返回YES則結束訊息轉發
// 返回NO則進入備胎

假如尚未實現的方法不是例項方法而是類方法, 則會呼叫另一個方法resolveClassMethod:

2. 備胎

動態方法解析失敗, 則呼叫這個方法

- (id)forwardingTargetForSelector:(SEL)selector
// selector : 那個未知的訊息
// 返回一個能響應該未知選擇子的備胎物件

通過備胎這個方法, 可以用”組合”來模擬出”多重繼承”.

3. 訊息簽名

備胎搞不定, 這個方法就準備要被包裝成一個NSInvocation物件, 在這裡要先返回一個方法簽名

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
// NSMethodSignature : 該selector對應的方法簽名

4. 完整的訊息轉發

給接收者最後一次機會把這個方法處理了, 搞不定就直接程式崩潰!

- (void)forwardInvocation:(NSInvocation *)invocation
// invocation : 封裝了與那條尚未處理的訊息相關的所有細節的物件

在這裡能做的比較現實的事就是 : 在觸發訊息前, 先以某種方式改變訊息內容, 比如追加另外一個引數, 或是改變訊息等等. 實現此方法時, 如果發現某呼叫操作不應該由本類處理, 可以呼叫超類的同名方法. 則繼承體系中的每個類都有機會處理該請求, 直到NSObject. 如果NSObject搞不定, 則還會呼叫doesNotRecognizeSelector:來丟擲異常, 此時你就會在控制檯看到那熟悉的unrecognized selector sent to instance..

訊息轉發流程

上面這4個方法均是模板方法,開發者可以override,由runtime來呼叫。最常見的實現訊息轉發,就是重寫方法3和4,忽略這個訊息或者代理給其他物件.

哈哈,到這裡,有關runtime的理論知識就先告於段落,在下篇文章中,你們要的乾貨來了—— runtime在實際開發中的應用,跳轉連結:點我跳轉

相關推薦

Linux小小白入門教程:顯示進入資料夾

以下操作在Linux終端進行。Linux因為許可權非常嚴格,所以暫時所有的命令操作全部是在/home資料夾下的/yangjw資料夾下進行。/yangjw資料夾就是登入使用者名稱所在的資料夾,出了此資料

Kotlin入門,LoopRange,Kotlin中區間的定義遍歷

Loop和Range Kotlin迴圈的使用和區間的定義和Java有很大的不同,如: fun main(args: Array<String>) { var nums = 1..100 //[1,100] for (num i

runtime入門精通—— 訊息傳送訊息轉發

前一篇文章中,我們介紹了runtime相關的術語的資料結構,檢視連結:runtime相關的術語的資料結構。本文主要講解與runtime相關的訊息傳送和訊息轉發兩個重要模組。 訊息傳送 訊息傳送舉例:下面這個OC程式碼 [person read:book

react.js入門精通——組件之間的數據傳遞

efault def 通道 span 代碼 serve urn div mar 一、組件之間在靜態中的數據傳遞 從上面的代碼我們可以看出,兩個組件之間的數據是分離,但如果我們有某種需求,將數據從一個組件傳到另一個組件中,該如何實現? 場景設計: 將Home.js中的Home

Matlab入門精通--常用函式

1、傅立葉(Fourier)變換及拉普拉斯(Laplace)變換 在MATLAB中,進行傅立葉變換的函式是: fourier(f,x,t):求函式f(x)的傅立葉像函式F(t)。 ifourier(F,t,x):求傅立葉像函式F(t)的原函式f(x)。   在MATLA

TensorFlow 入門精通:使用 TensorFlow 實現 RNN

使用 TensorFlow 很大的一個原因是其對 RNN/LSTM 支援較好。作為理解 RNN/LSTM 基礎,建議閱讀經典文獻:以下為程式碼。# Copyright 2015 Google Inc. All Rights Reserved. # # Licensed und

ZED-Board入門精通:軟硬體協同設計

Zynq最大的優勢在於,同時具備軟體、硬體、IO可程式設計,即All Programmable。在設計Zynq過程中,同樣要建立一種意識,就是從原來單純的軟體思維(或單純的硬體思維)中解脫,轉向軟硬體協同設計的開發方法。 軟體設計,即基於ARM的軟體開發,我們第三節裡面已

Vue學習入門精通

  今天主要學習一下表單輸入繫結。v-model指令在表單<input> <textarea> <select> 等元素上建立雙向資料繫結。它會根據控制元件型別自動選取正確的方法來更新資料。   v-model會忽略所有表單

CUDA入門精通:執行緒並行

多執行緒我們應該都不陌生,在作業系統中,程序是資源分配的基本單元,而執行緒是CPU時間排程的基本單元(這裡假設只有1個CPU)。 將執行緒的概念引申到CUDA程式設計中,我們可以認為執行緒就是執行CUDA程式的最小單元,前面我們建立的工程程式碼中,有個核函式概念不知各位

Spring Boot入門精通多資料來源配置實現及原始碼分析

多資料來源配置在專案軟體中是比較常見的開發需求,Spring和Spring Boot中對此都有相應的解決方案可供大家參考。在Spring Boot中,如MyBatis、JdbcTemplate以及Jpa都可以配置多資料來源。 本文在前一篇“Spring Boot從入門到精通(四)連線MySQL資料庫(附原始碼

TensorFlow 入門精通:安裝使用

安裝過程 目前較為穩定的版本為 0.12,本文以此為例。其他版本請讀者自行甄別安裝步驟是否需要根據實際情況修改。 TensorFlow 支援以下幾種安裝方式: PIP 安裝 原始碼編譯安裝 Docker 映象安裝 PIP 安裝

OllyDBG 入門系列訊息斷點及 RUN 跟蹤

OllyDBG 入門系列(五)-訊息斷點及 RUN 跟蹤作者:CCDebuger找了幾十個不同語言編寫的 crackme,發現只用訊息斷點的話有很多並不能真正到達我們要找的關鍵位置,想想還是把訊息斷點和 RUN 跟蹤結合在一起講,更有效一點。關於訊息斷點的更多內容大家可以參

Vue入門系列Vue實例詳解與生命周期

auto res context mode parent all from bool silent 【入門系列】 【本文轉自】   http://www.cnblogs.com/fly_dragon Vue的實例是Vue框架的入口,其實也就是前端的ViewM

Scala入門系列:面向對象之類

important ica back ember const 就會 out 不用 spa // 定義類,包含field以及method class HelloWorld { private var name = "Leo" def sayHello() { prin

Python入門之文件操作字符編碼

Python 文件操作和字符編碼 1、文件操作 1、文件操作流程: 打開文件,得到文件句柄並賦值給一個變量===> file = open("yesterday",encoding="utf-8") 通過句柄對文件進行操作 關閉文件 ==> file.close() 1.2、打開文件的

elasticsearch入門使用 kibana安裝使用

png elastic sha img 相關 復制 logstash per usr Kibana User Guide 一、UI安裝 https://www.elastic.co/downloads/kibana 下載rpm直接運行即可 二、參數配置 find / -

MySQL入門之高可用架構MHA

數據節點 ability ast 圖片 故障轉移 5.5 架構 日本 丟失 一、MHA原理 1、簡介: MHA(Master High Availability)目前在MySQL高可用方面是一個相對成熟的解決方案,它由日本DeNA公司youshimaton(現就職於

docker零開始堆棧初體驗,stacks

開始 services 信息 工作 run cer cal tail int 先決條件 安裝Docker 1.13或更高版本。 獲取Docker Compose,請參考第三節 按照第四節中的描述獲取Docker Machine。 在第二節中了解如何創建容器。

NS2入門學習之分裂物件模型TclCL

 TclCL其實就是連線C++與Otcl,實現兩者的互相操作和兩者之間類的對應. NS中使用兩種語言原因: C++執行速度較快,是強制型別語言(進行嚴格的資料型別檢查),容易實現複雜的資料型別和精確/複雜的演算法。但是修改/debug和重新編譯時間較長,所以適合完成網路協

Docker入門教程Docker安全

【編者的話】DockOne組織翻譯了Flux7的Docker入門教程,本文是系列入門教程的第五篇,介紹了Docker的安全問題,依然是老話重談,入門者可以通過閱讀本文快速瞭解。 我們必須高度重視開源軟體的安全問題,當開發者在使用Docker時,從本地構建應用程式到生產環境部署是沒有任何差異的(譯