1. 程式人生 > >iOS Runtime 執行時之三:訊息處理機制

iOS Runtime 執行時之三:訊息處理機制

前面我們討論了Runtime中對類和物件的處理,及對成員變數與屬性的處理。這一章,我們就要開始討論Runtime中最有意思的一部分:訊息處理機制。我們將詳細討論訊息的傳送及訊息的轉發。不過在討論訊息之前,我們先來了解一下與方法相關的一些內容。

基礎資料型別

SEL

SEL又叫選擇器,是表示一個方法的selector的指標,其定義如下:

1 typedef struct objc_selector *SEL;

objc_selector結構體的詳細定義沒有在<objc/runtime.h>標頭檔案中找到。方法的selector用於表示執行時方法的名字。

Objective-C在編譯時,會依據每一個方法的名字、引數序列,生成一個唯一的整型標識(Int型別的地址),這個標識就是SEL。如下程式碼所示:

1 2 SEL sel1 = @selector(method1); NSLog(@"sel : %p", sel1);

上面的輸出為:

1 2014-10-30 18:40:07.518 RuntimeTest[52734:466626] sel : 0x100002d72

兩個類之間,不管它們是父類與子類的關係,還是之間沒有這種關係,只要方法名相同,那麼方法的SEL就是一樣的。每一個方法都對應著一個SEL。所以在Objective-C同一個類(及類的繼承體系)中,不能存在2個同名的方法,即使引數型別不同也不行。相同的方法只能對應一個SEL。這也就導致Objective-C在處理相同方法名且引數個數相同但型別不同的方法方面的能力很差。如在某個類中定義以下兩個方法:

1 2 - (void)setWidth:(int)width; - (void)setWidth:(double)width;

這樣的定義被認為是一種編譯錯誤,所以我們不能像C++, C#那樣。而是需要像下面這樣來宣告:

1 2 -(void)setWidthIntValue:(int)width; -(void)setWidthDoubleValue:(double)width;

當然,不同的類可以擁有相同的selector,這個沒有問題。不同類的例項物件執行相同的selector時,會在各自的方法列表中去根據selector去尋找自己對應的IMP。

工程中的所有的SEL組成一個Set集合,Set的特點就是唯一,因此SEL是唯一的。因此,如果我們想到這個方法集合中查詢某個方法時,只需要去找到這個方法對應的SEL就行了,SEL實際上就是根據方法名hash化了的一個字串,而對於字串的比較僅僅需要比較他們的地址就可以了,可以說速度上無語倫比!!但是,有一個問題,就是數量增多會增大hash衝突而導致的效能下降(或是沒有衝突,因為也可能用的是perfect hash)。但是不管使用什麼樣的方法加速,如果能夠將總量減少(多個方法可能對應同一個SEL),那將是最犀利的方法。那麼,我們就不難理解,為什麼SEL僅僅是函式名了。

本質上,SEL只是一個指向方法的指標(準確的說,只是一個根據方法名hash化了的KEY值,能唯一代表一個方法),它的存在只是為了加快方法的查詢速度。這個查詢過程我們將在下面討論。

我們可以在執行時新增新的selector,也可以在執行時獲取已存在的selector,我們可以通過下面三種方法來獲取SEL:

  1. sel_registerName函式
  2. Objective-C編譯器提供的@selector()
  3. NSSelectorFromString()方法

IMP

IMP實際上是一個函式指標,指向方法實現的首地址。其定義如下:

1 id (*IMP)(id, SEL, ...)

這個函式使用當前CPU架構實現的標準的C呼叫約定。第一個引數是指向self的指標(如果是例項方法,則是類例項的記憶體地址;如果是類方法,則是指向元類的指標),第二個引數是方法選擇器(selector),接下來是方法的實際引數列表。

前面介紹過的SEL就是為了查詢方法的最終實現IMP的。由於每個方法對應唯一的SEL,因此我們可以通過SEL方便快速準確地獲得它所對應的IMP,查詢過程將在下面討論。取得IMP後,我們就獲得了執行這個方法程式碼的入口點,此時,我們就可以像呼叫普通的C語言函式一樣來使用這個函式指標了。

通過取得IMP,我們可以跳過Runtime的訊息傳遞機制,直接執行IMP指向的函式實現,這樣省去了Runtime訊息傳遞過程中所做的一系列查詢操作,會比直接向物件傳送訊息高效一些。

Method

介紹完SEL和IMP,我們就可以來講講Method了。Method用於表示類定義中的方法,則定義如下:

1 2 3 4 5 6 7 typedef struct objc_method *Method; struct objc_method { SEL method_name                 OBJC2_UNAVAILABLE;  // 方法名 char *method_types                  OBJC2_UNAVAILABLE; IMP method_imp                      OBJC2_UNAVAILABLE;  // 方法實現 }

我們可以看到該結構體中包含一個SEL和IMP,實際上相當於在SEL和IMP之間作了一個對映。有了SEL,我們便可以找到對應的IMP,從而呼叫方法的實現程式碼。具體操作流程我們將在下面討論。

objc_method_description

objc_method_description定義了一個Objective-C方法,其定義如下:

1

相關推薦

iOS Runtime 執行訊息處理機制

前面我們討論了Runtime中對類和物件的處理,及對成員變數與屬性的處理。這一章,我們就要開始討論Runtime中最有意思的一部分:訊息處理機制。我們將詳細討論訊息的傳送及訊息的轉發。不過在討論訊息之前,我們先來了解一下與方法相關的一些內容。 基礎資料型別

iOS學習筆記56(Runtime)-Objective-C Runtime 執行方法與訊息

前面我們討論了Runtime中對類和物件的處理,及對成員變數與屬性的處理。這一章,我們就要開始討論Runtime中最有意思的一部分:訊息處理機制。我們將詳細討論訊息的傳送及訊息的轉發。不過在討論訊息之前,我們先來了解一下與方法相關的一些內容。 基礎資料型別 SEL

Objective-C Runtime 執行方法與訊息

前面我們討論了Runtime中對類和物件的處理,及對成員變數與屬性的處理。這一章,我們就要開始討論Runtime中最有意思的一部分:訊息處理機制。我們將詳細討論訊息的傳送及訊息的轉發。不過在討論訊息之前,我們先來了解一下與方法相關的一些內容。 基礎資料型別 SEL

[ObjectC]Runtime執行方法與訊息

這一章,我們就要開始討論Runtime中最有意思的一部分:訊息處理機制。我們將詳細討論訊息的傳送及訊息的轉發。 基礎資料型別 SEL SEL又叫選擇器,是表示一個方法的selector的指標,其定義如下:typedef struct objc_selector *SEL;o

Objective-C Runtime 執行協議與分類

Objective-C中的分類允許我們通過給一個類新增方法來擴充它(但是通過category不能新增新的例項變數),並且我們不需要訪問類中的程式碼就可以做到。 Objective-C中的協議是普遍存在的介面定義方式,即在一個類中通過@protocol定義介面,在另外

Objective-C Runtime 執行拾遺

前面幾篇基本介紹了runtime中的大部分功能,包括對類與物件、成員變數與屬性、方法與訊息、分類與協議的處理。runtime大部分的功能都是圍繞這幾點來實現的。 本章的內容並不算重點,主要針對前文中對Objective-C Runtime Reference內容遺漏

Objective-C Runtime 執行成員變數與屬性

在前面一篇文章中,我們介紹了Runtime中與類和物件相關的內容,從這章開始,我們將討論類實現細節相關的內容,主要包括類中成員變數,屬性,方法,協議與分類的實現。 本章的主要內容將聚集在Runtime對成員變數與屬性的處理。在討論之前,我們先介紹一個重要的概念:型別

Objective-C Runtime 執行Method Swizzling

理解Method Swizzling是學習runtime機制的一個很好的機會。在此不多做整理,僅翻譯由Mattt Thompson發表於nshipster的Method Swizzling一文。 Method Swizzling是改變一個selector的實際實現的

iOS runtime執行特性解決陣列越界問題。

 @interface NSObject (Exchange) -(void)swizzleMethod:(SEL)OldSel withNewMethod:(SEL)NewSel;  @end#import   "NSObject+Exchange.h" @implem

iOS runtime執行的用法(一)

<span style="color:#333333">RunTime簡稱執行時。OC就是執行時機制,也就是在執行時候的一些機制,其中最主要的是訊息機制。</span> 編譯時: 即編譯器對語言的編譯階段,編譯時只是對語言進行最基本的檢查

【深入Java虛擬機器】類載入機制

類載入過程     類從被載入到虛擬機器記憶體中開始,到卸載出記憶體為止,它的整個生命週期包括:載入、驗證、準備、解析、初始化、使用和解除安裝七個階段。它們開始的順序如下圖所示:     其中類載入的過程包括了載入、驗證、準備、

AndroidHandler 二事(訊息處理機制

主要內容 Handler 的訊息處理機制。 主要是關於 MessageQueue、Message、Looper、Handler 之間的關係。 Android 訊息驅動機制的四要素 接收訊息的訊息佇列–>MessageQueue 阻塞式的從訊

Android Handler(子執行緒Handler)非同步訊息處理機制的妙用(活用訊號量) 建立強大的圖片載入類

最近建立了一個群,方便大家交流,群號:55032675 上一篇部落格介紹了Android非同步訊息處理機制,如果你還不瞭解,可以看:Android 非同步訊息處理機制 讓你深入理解 Looper、Handler、Message三者關係 。那篇部落格的最後

iOS開發關於Runtime執行類與物件

Objective-C語言是一門動態語言,它將很多靜態語言在編譯和連結時期做的事放到了執行時來處理。這種動態語言的優勢在於:我們寫程式碼時更具靈活性,如我們可以把訊息轉發給我們想要的物件,或者隨意交換一個方法的實現等。 這種特性意味著Objective-C不僅需要一個編譯器,還需要一個執行時系統

Windows訊息響應機制執行緒與訊息佇列

當一個執行緒第一次被建立時,系統假定執行緒不會用於任何與使用者相關的任務。這樣可以減少執行緒對系統資源的要求。但是,一旦該執行緒呼叫一個與圖形使用者介面有關的函式 ( 如檢查它的訊息佇列或建立一個視窗 ),系統就會為該執行緒分配一些另外的資源,以便它能夠執行與使用者介面有關

C++11併發學習執行緒同步

1.<mutex> 標頭檔案介紹  (1)Mutex系列類(四種) std::mutex,最基本的 Mutex 類。 std::recursive_mutex,遞迴 Mutex 類。 std::time_mutex,定時 Mutex 類。 std::recursive_ti

Objective-C Runtime 執行之一類與物件

Objective-C語言是一門動態語言,它將很多靜態語言在編譯和連結時期做的事放到了執行時來處理。這種動態語言的優勢在於:我們寫程式碼時更具靈活性,如我們可以把訊息轉發給我們想要的物件,或者隨意交換一個方法的實現等。 這種特性意味著Objective-C不僅需要一

iOSruntime(執行)的簡單介紹與應用

最近學習到runtime這一塊知識了所以就總結一下,以備以後要用。但是由於runtime這一塊的知識比較多所以今天在這裡只是做一個簡單的總結。 一、什麼是Runtime? Objective-C runtime是一個實現Objective-C語言的

hadoop初識搭建hadoop環境(配置HDFS,Yarn及mapreduce 執行在yarn)上及執行模式(本地模式,偽分散式和分散式介)

--===============安裝jdk(解壓版)================== --root 使用者登入 --建立檔案層級目錄    /opt下分別 建 modules/softwares/datas/tools 資料夾 --檢視是否安裝jdk    rpm -

趣談iOS執行方法呼叫原理

導語 訊息轉發 OC的動態語言特性 1動態型別 2動態繫結 3動態載入 導語 一個成熟的計算機語言必然有豐富的體系,複雜的容錯機制,處理邏輯以及判斷邏輯。但這些複雜的邏輯都是圍繞一個主線豐富和展開的,所以在學習計算機語言的時候,先掌握核心