1. 程式人生 > >objective-c中的訊息響應機制

objective-c中的訊息響應機制

        學習objective-c必然會接觸訊息操作,下面就訊息的響應過程做一下分析和總結。

        首先我們需要了解oc中的3種物件:例項物件;類物件;元類物件。

例項物件中儲存著的主要結構有:isa指標,指向其類物件;例項成員變數;還有count引用計數等。

類物件中儲存的主要資料結構:isa指標,指向該類的元類物件;super指標,指向父類的類物件;例項方法(’ – ‘ 開頭的方法)呼叫地址對映表;

元類物件儲存的主要資料結構:isa指標,指向NSObject的元類物件;super指標,指向父類的元類物件;類方法(’+’開頭的方法)呼叫地址對映表;

當我們向一個物件(不一定是例項物件)傳送訊息時,首先將通過該物件的isa指標來到對應的另一個物件中(類物件或元類物件),注意:

isa指標在整個訊息響應的過程中會且僅會使用一次。先查詢cache中是否已有對應的函式地址對映,有就直接使用。

       注意:每個類物件(包括元類)都有一個獨立的cache,用於儲存繼承鏈中和自身類中定義的方法。如果對應訊息存在於cache中,那它僅稍微慢於函式呼叫。隨著程式的執行所有cache中的方法將動態增長。

如果cache中沒有,再查詢物件內的dispatch table。若還是沒有找到對應的響應函式,則沿著super指標在父類相應物件中進一步查詢。

官方文件的示意圖如下:

 

若到根類也沒有找到的時候將會向物件傳送forwardInvocation:訊息,該訊息預設呼叫doesNotRecognizeSelector:方法,該方法將生成一個錯誤訊息表示異常發生。

forwardInvocation:訊息定義在NSObject中,使用者可以重定義該方法,當被髮送不能處理的訊息時,就可以將其轉發給其他物件,或者自己執行錯誤處理。

下面舉個簡單的例子說明一下:

類A與類B的宣告如下圖


A繼承了NSObject,而B繼承了A。三個物件間的isa與super_ class指標的指向情況如下圖。

 

此時我們可以做簡單呼叫


注意:其中hash為NSObject的類方法,isProxy為NSObject的例項方法。

1.執行[a isProxy]時,訊息首先通過isa指標從A的例項物件(a)到達A的類物件,發現A的類物件中並無對應的方法,於是通過super_class指標到達NSObject的類物件;在NSObject類物件中找到對應的方法並執行成功。

2.[b BClassMethod]之所以出錯,因為傳送訊息首先到達B的類物件(通過isa),而B的類方法儲存在B的元類物件中,通過super_class指標無法到達(需第二次通過isa指標,但是該指標在一次訊息傳送過程中能且只能使用一次)。

3.[B isProxy]的成功執行關鍵在於NSObject的元類物件的super_class指標指向了NSObject類物件。所以B的元類物件通過super_class找到了對應的例項方法。

4.[[[A class] class] class]:從原理上來說class是可以無限呼叫的,因為class方法返回isa指標指向的結構,而最終NSObject元類的isa指標指向自身。

總結:

例項物件可以呼叫自身及祖先的例項方法;但不能呼叫類方法,因為類方法在元類物件中,需第二次使用isa指標。

類物件可以呼叫自身及祖先中的類方法,同時還可以呼叫NSObject(根類)中定義的例項方法(因為所有元類的isa都指向NSObject的元類物件,而NSObject元類物件的super指標指向了NSObject的類物件,類物件中定義了例項方法)。

希望對大家有幫助,如若有誤,敬請指正。

相關推薦

C#訊息處理機制(事件與委託)

編寫過Windows桌面應用程式的人都知道,微軟的Windows作業系統與應用程式之間的通訊絕大部分是基於訊息迴圈機制的。在VC++中,程式使用GetMessage,TranslateMessage,DispatchMessage語句從訊息佇列中獲取訊息,轉換訊息並且將訊息分發到目標視窗的過程函式,並由過程

objective-c訊息響應機制

        學習objective-c必然會接觸訊息操作,下面就訊息的響應過程做一下分析和總結。         首先我們需要了解oc中的3種物件:例項物件;類物件;元類物件。 例項物件中儲存著的主要結構有:isa指標,指向其類物件;例項成員變數;還有count引用計數

Objective-C訊息傳送總結

關於OC中的訊息傳送的實現,在去年也看過一次,當時有點不太理解,但是今年再看卻很容易理解。 我想這跟知識體系的構建有關,如果你不認識有磚、水泥等這些建築的基本組成部分,那麼我們應該很難理解建築是怎麼建造出來的吧? 學習新知識,應該也是同樣的道理! 資料 今年再看 訊息傳送機制時,

Objective-C的記憶體管理機制

從蘋果的官方文件來看,OC對應用程式的記憶體管理提供了2種方法。 第一種即“manual retain-release”(MRR),手動保留釋放,也可理解為手動引用計數。 第二種,“Automatic Reference Counting”(ARC),自動引用計數。但是ARC並不等同垃圾回收。在蘋果的官方

ios學習路線—Objective-C(Runtime訊息機制)

RunTime簡稱執行時。就是系統在執行的時候的一些機制,其中最主要的是訊息機制。對於C語言,函式的呼叫在編譯的時候會決定呼叫哪個函式( C語言的函式呼叫請看這裡 )。編譯完成之後直接順序執行,無任何二義性。OC的函式呼叫成為訊息傳送。屬於動態呼叫過程。在編譯的時候並不能決定真正呼叫哪個函式(事實證明,在編

Objective-C 的Runtime的詳細使用

enc ring 博客 document 每次 tps htm lec guid Runtime全面了解 一直以來,OC被大家冠以動態語言的稱謂,其實是因為OC中包含的runtime機制。Runtime 又叫運行時,是一套底層的 C 語言 API,其為 iO

objective-c 數據類型之四 字典(NSDictionary)

bject ted ray 初始化 -c lec com lock led // 1. 字典初始化、賦值方式1 NSMutableDictionary *m_dictionary = [[NSMutableDictionary alloc] initWithCa

objective-c 數據類型之二 字符串(NSString)

option 大小 edas 字符串長度 seq scan 後者 code form // 1. 聲明一個NSString對象,註意對象前要加‘*’。 NSString *string1; // 賦值方

Objective-C內存管理機制

析構函數 tomat 機制 如果 ngs 都是 範圍 管理 c內存 Objective-C內存管理機制分成兩種:MRC和ARC (1)MRC (Manual Reference Counting) 當前系統默認都是采用ARC,如果想使用MRC需要在build settin

Objective-C的@property和@synthesize用法

有時 頭文件 關鍵字 nbsp nsa atomic 所有者 ica 風險 描述 @代表“Objective-C”的標誌,證明您正在使用Objective-C語言。 是Objective-C語言關鍵詞。 @property與@synthesize配對使用。 功能:讓編譯

Objective-C,類方法的getter和setter可以用點運算符嗎?

clang col 靜態變量 變量 uri family lan getc sta Objective-C中,對象實例property的getter和setter可以使用點運算符來操作,那麽類方法的getter和setter可以使用點運算嗎? 答案是肯定的。 看如下代碼

C#使用事件機制實現執行緒間的通訊

在圖形介面中的運用程式中,通常是主執行緒負責UI人機互動,而將需要迴圈執行和耗資源的邏輯程式碼和複雜的業務實現以及資料互動放到單獨一個執行緒裡執行。這樣可以保證主執行緒UI可以正常進行人機互動。 而執行緒之間的資料互動,就涉及了執行緒通訊。這裡將通過一個給MCU升級韌體程式的IAP(在應用

詳解Objective-C委託和協議

Objective-C委託和協議本沒有任何關係,協議如前所述,就是起到C++中純虛類的作用,對於“委託”則和協議沒有關係,只是我們經常利用協議還實現委託的機制,其實不用協議也完全可以實現委託。 AD:51CTO 網+ 第十二期沙龍:大話資料之美_如何用資料驅動使用者體驗

探究Objective-C關聯物件原理

一、實際問題 1.提出問題 首先,一切都要從一個問題開始:在Objective-C中,能否在Category中為類新增屬性及對應的例項變數? 該題的答案是:不能。 2.分析解答 為什麼不能通過Category來為Objective-C的類新增屬性及對應的例項變數

Objective-c.m、.h、.mm檔案

在使用Objective-c的工程中,會存在.m、.h、.mm這三種不同字尾名的檔案,它們的區別如下: .h :標頭檔案,它包含類名,類繼承的父類,還有方法和變數的宣告。它定義的類的成員變數以及方法等等是公開的,外部是可以訪問的。 .m :實現檔案,可以包含Objective-C和C程式碼。

Objective-CC語言使用初步學習

最近在進行iOS的深入學習,看過一些部落格後意識到自己的程式碼寫的過於臃腫。我從開始學習到現在的業務熟練都是使用的最基本的MVC模式,於是MVC中的C--controller程式碼十分臃腫,讓接手程式碼的人無從下手。在網上查閱多篇部落格後,才瞭解到有多種設計模式,雖然各有缺點,但是能讓我借鑑到許多方

Objective-C NULL、nil、Nil、NSNull 的定義及不同

理解”不存在“的概念不僅僅是一個哲學的問題,也是一個實際的問題。我們是有形宇宙的居民,而原因在於邏輯宇宙的存在不確定性。作為一個邏輯系統的物理體現,計算機面臨一個棘手的問題,就是如何用”存在“表達”不存在“。–摘自 NSHipster 這段話讀起來怪怪的,畢竟是翻譯過來的,

Objective-C的老闆是這樣發通知的(Notification)

    ​    ​通知(Notification)簡單的類比一下,公司的老總給下面的員工發通知啦,說明天公司要上市,各部門做一下準備工作。等通知發完,各部門收到後各司其職,做著自己該做的東西。假如Boss是通過公司的內部論壇傳送的通知,那麼Boss就是傳送通知的物件,而公司員工就是通知的接受方,而公司的內部

iOS --- Objective-C類的成員變數與屬性

在Objective-C的類與物件的概念中. 成員變數與屬性的區別與聯絡一直沒有搞清楚. 直到學習了慕課網上的這個課程Objective-C面向物件初體驗, 才算真正有了點感覺了. 最關鍵的結論就是: 類內使用成員變數{}, 類外使用屬性@property.

Objective-C的反射和反射工廠

  程式中可能會出現大量的if-else或者switch-case來選擇一系列類中的某個類進行操作,利用反射(Reflection)就可以避免這些重複判斷工作。   反射在Java中封裝了類來實現,在Objective-C裡面要自己來實現,好在不是很難。   我們的目的是通過傳入一個類名字串,把字串類