1. 程式人生 > >Objective-C與Runtime的那點事兒訊息機制

Objective-C與Runtime的那點事兒訊息機制

最近在找工作,Objective-C中的Runtime是經常被問到的一個問題,幾乎是面試大公司必問的一個問題。當然還有一些其他問題也幾乎必問,例 如:RunLoop,Block,記憶體管理等。其他的問題如果有機會我會在其他文章中介紹。本篇文章主要介紹RunTime。

RunTime簡稱執行時。就是系統在執行的時候的一些機制,其中最主要的是訊息機制。對於C語言,函式的呼叫在編譯的時候會決定呼叫哪個函式( C語言的函式呼叫請看這裡 )。編譯完成之後直接順序執行,無任何二義性。OC的函式呼叫成為訊息傳送。屬於動態呼叫過程。在編譯的時候並不能決定真正呼叫哪個函式(事實證明,在編 譯階段,OC可以呼叫任何函式,即使這個函式並未實現,只要申明過就不會報錯。而C語言在編譯階段就會報錯)。只有在真正執行的時候才會根據函式的名稱找 到對應的函式來呼叫。

那OC是怎麼實現動態呼叫的呢?下面我們來看看OC通過傳送訊息來達到動態呼叫的祕密。假如在OC中寫了這樣的一個程式碼:

1 [obj makeText];

其中obj是一個物件,makeText是一個函式名稱。對於這樣一個簡單的呼叫。在編譯時RunTime會將上述程式碼轉化成

1 objc_msgSend(obj,@selector(makeText));

首先我們來看看obj這個物件,iOS中的obj都繼承於NSObject。

1 2 3 @interface NSObject <nsobject> { Class isa  OBJC_ISA_AVAILABILITY;
}</nsobject>

在NSObjcet中存在一個Class的isa指標。然後我們看看Class:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 typedef struct objc_class *Class; struct objc_class { Class isa; // 指向metaclass Class super_class ; // 指向其父類 const char *name ; // 類名 long version ; // 類的版本資訊,初始化預設為0,可以通過runtime函式class_setVersion和class_getVersion進行修改、讀取
long info; // 一些標識資訊,如CLS_CLASS (0x1L) 表示該類為普通 class ,其中包含物件方法和成員變數;CLS_META (0x2L) 表示該類為 metaclass,其中包含類方法; long instance_size ; // 該類的例項變數大小(包括從父類繼承下來的例項變數); struct objc_ivar_list *ivars; // 用於儲存每個成員變數的地址 struct objc_method_list **methodLists ; // 與 info 的一些標誌位有關,如CLS_CLASS (0x1L),則儲存物件方法,如CLS_META (0x2L),則儲存類方法; struct objc_cache *cache; // 指向最近使用的方法的指標,用於提升效率; struct objc_protocol_list *protocols; // 儲存該類遵守的協議 }

我們可以看到,對於一個Class類中,存在很多東西,下面我來一一解釋一下:

Class isa:指向metaclass,也就是靜態的Class。一般一個Obj物件中的isa會指向普通的Class,這個Class中儲存普通成員變數和對 象方法(“-”開頭的方法),普通Class中的isa指標指向靜態Class,靜態Class中儲存static型別成員變數和類方法(“+”開頭的方 法)。

Class super_class:指向父類,如果這個類是根類,則為NULL。

下面一張圖片很好的描述了類和物件的繼承關係:

iuqQFnm.png

注意:所有metaclass中isa指標都指向跟metaclass。而跟metaclass則指向自身。Root metaclass是通過繼承Root class產生的。與root class結構體成員一致,也就是前面提到的結構。不同的是Root metaclass的isa指標指向自身。

Class類中其他的成員這裡就先不做過多解釋了,下面我們來看看:

@selector (makeText):這是一個SEL方法選擇器。SEL其主要作用是快速的通過方法名字(makeText)查詢到對應方法的函式指標,然後呼叫其函 數。SEL其本身是一個Int型別的一個地址,地址中存放著方法的名字。對於一個類中。每一個方法對應著一個SEL。所以iOS類中不能存在2個名稱相同 的方法,即使引數型別不同,因為SEL是根據方法名字生成的,相同的方法名稱只能對應一個SEL。

下面我們就來看看具體訊息傳送之後是怎麼來動態查詢對應的方法的。

首先,編譯器將程式碼[obj makeText];轉化為objc_msgSend(obj, @selector (makeText));,在objc_msgSend函式中。首先通過obj的isa指標找到obj對應的class。在Class中先去cache中 通過SEL查詢對應函式method(猜測cache中method列表是以SEL為key通過hash表來儲存的,這樣能提高函式查詢速度),若 cache中未找到。再去methodList中查詢,若methodlist中未找到,則取superClass中查詢。若能找到,則將method加 入到cache中,以方便下次查詢,並通過method中的函式指標跳轉到對應的函式中去執行。

相關推薦

Objective-CRuntime事兒訊息機制

最近在找工作,Objective-C中的Runtime是經常被問到的一個問題,幾乎是面試大公司必問的一個問題。當然還有一些其他問題也幾乎必問,例 如:RunLoop,Block,記憶體管理等。其他的問題如果有機會我會在其他文章中介紹。本篇文章主要介紹RunTime。 R

淺談Swift和Objective-C之間的事。。。

Swift 是一種新的程式語言,用於編寫 iOS 和 OS X 應用。Swift 結合了 C 和 Objective-C 的優點並且不受C相容性的限制。Swift 採用安全的程式設計模式並添加了很多新特性,這將使程式設計更簡單,更靈活,也更有趣。Swift 是基

SElinuxvsftp事兒

255  yum install vsftp*      #安裝vsftp256  ls257  dd if=/dev/zero of=/dev/test.img bs=20M count=5#新建一個100M的映象檔案258  ls259  mkfs.ext4 /dev/test.img      #格

《開源框架事兒19》:特斯拉建“樁”開源的生命力

充電站 otto 期權 eas gb2 平臺 程序 蘋果 名詞 在美國的矽谷,在中國的中關村,很多的技術先驅者懷揣夢想。用激情不懈地追求著他們宏遠的目標和巨大的個人財富。開源。正在成為這個時代眼下最火熱的名詞之中的一個。開源精神,作為一種合作協同的驅動力,正在發展為一種更

[jms事兒] JMS 訊息傳送模式、訊息簽收以及spring jmsTemplate配置

Activemq支援兩種訊息傳送模式:PERSISTENT (持久訊息)和 NON_PERSISTENT(非持久訊息) 從字面意思就可以瞭解,這是兩種正好相反的模式。 1、PERSISTENT 持久訊息 是activemq預設的傳送方式,此方式下的訊息在配合activemq

unityios互動事兒

unity與ios互動 Unity中呼叫Objective-C/C++方法 1、[DllImport("__Internal")] 特性 在Unity新建專案中,Progect --> Create --> C# Script ,然後使用 [DllIm

Spring Boot多資料來源事兒~

持續原創輸出,點選上方藍字關注我 目錄 前言寫這篇文章的目的什麼是多資料來源?何時用到多資料來源?整合單一的資料來源整合Mybatis多資料來源如何整合? 什麼是動態資料來源?資料來源切換如何保證執行緒隔離?如何構造一個動態資料來源?定義一個註解如何與Mybatis整合?演示 總結 前言 大約在19年

《開源框架事兒25》:對框架模板引擎實現方式的改造實錄

port 內嵌 代碼調試 iter put 文件路徑 children nts fault 點滴悟透設計思想,Tiny模板引擎優化實錄! 增加框架設計興趣小組:http://bbs.tinygroup.org/group-113-1.html Tiny模板引擎的實

關於LOG事兒

java;源碼時代日誌,作為記錄系統中硬件、軟件和系統問題的信息,同時還可以監視系統中發生的事件,是產品運維中非常重要的數據之一,用戶可以通過它來檢查錯誤發生的原因,或者尋找受到攻擊時攻擊者留下的痕跡。日誌根據程序和不同領域,可分為消息日誌,事件日誌,數據庫日誌等等。對於Java工程師而言,程序代碼的日誌是由

談談源碼管理事兒(一)——源碼管理十誡(轉)

我不 evel .html 文件夾 jetbrains enable thum XML 構建 引言: 若是還有能夠毫無偏見地涉及各個編程語言。比源碼管理軟件更必要的工具。我倒是非常想見識一下。源碼管理軟件是我們工作的必備工具,是很多開發團隊的血液。那為什麽我們都

Objective-C & Runtime

ive tex req exec apt .com provide see part https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ProgrammingWithObje

css中關於居中的事兒

效果圖 單元格 meta 得到 部分 邊距 絕對定位 lin ble   關於居中,無論是水平居中,還是垂直居中都有很多方式,下面我來介紹一些常用的。 第一部分:水平居中   1.實現行內元素的居中。方法:在行內元素外面的塊元素的樣式中添加:text-align:cen

MVC之前的事兒 ---- 系列文章

需要 cnblogs post omx pip 實現原理 內容 activator div MVC之前的那點事兒系列,是筆者在2012年初閱讀MVC3源碼的時候整理的,主要講述的是從HTTP請求道進入MVCHandler之前的內容,包括了原創,翻譯,轉載,整理等各類型文

php curl事兒

func utf8 格式 姓名 url orm peer div 是否 curl是最常用功能之一初始化句柄 $ch = curl_init(); post 傳$data 1. 如果$data是字符串,則Content-Type是application/x-ww

C#編譯器優化

代碼質量 配置 需要 但是 strong -a tool -- dbo 使用C#編寫程序,給最終用戶的程序,是需要使用release配置的,而release配置和debug配置,有一個關鍵區別,就是release的編譯器優化默認是啟用的。 優化代碼開關即optimize開關

反編譯事兒

kms ros ogr files 位置 file bsp 所在 命令 1.ildasm.exe 所在文件夾位置 C:\Program Files (x86)\Microsoft SDKs\Windows 2.ilasm.exe 所在文件夾位置:cd C:\Windows

Maven 事兒(轉)

做到 conn active cep ant tab name www color 0. 前言 Jason Van Zyl,在 Java 十大風雲人物排行榜上或許會看到他。 這兄弟是幹嘛的? 他就是 Maven 的創始人,人們都尊稱他為“Maven 他爸&

聊聊Cisco 3650交換機系統升級事兒

roc ase necessary 文件 -i 文章 ota catalyst ive 說起思科的交換機升級,大多數人想到的是以下幾步:(1)把系統.bin文件通過TFTP或是FTP上傳到交換機中(2)將原有.bin文件刪除,重啟(或是手動設置引導順序)(3)重啟後升級完成

importnew:Map大家族的事兒

.html dha osc lan hash jdk7 .net href head Map大家族的那點事兒(1) :Map Map大家族的那點事兒(2) :AbstractMap Map大家族的那點事兒(3) :TreeMap Map大家族的那點事兒(4) :HashMa

操作系統和Web服務器事兒

memory ... 還需 不同 圖片 web kill -o 傷感 又一個進程啟動了,操作系統老大嘆了一口氣,畢竟自己的肩頭又多了一份責任。 讓人煩惱的是,新來的家夥們很無知,幾乎就是一張白紙。有些老實本分的會按照自己的規矩來做事,有些刺頭兒喜歡問這問那,時不時還想搞點非