iOS開發Runtime那些事

2021-07-10 03:50:14 字數 2821 閱讀 5130

objective-c中的runtime是經常被問到的乙個問題,幾乎是面試大公司必問的乙個問題。當然還有一些其他問題也幾乎必問,例 如:runloop,block,記憶體管理等。本篇文章主要介紹runtime。

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

那oc是怎麼實現動態呼叫的呢?下面我們來看看oc通過傳送訊息來達到動態呼叫的秘密。假如在oc中寫了這樣的乙個**:

[obj maketext];

其中obj是乙個物件,maketext是乙個函式名稱。對於這樣乙個簡單的呼叫。在編譯時runtime會將上述**轉化成

objc_msgsend(obj,@selector(maketext));

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

@inte***ce nsobject

在nsobjcet中存在乙個class的isa指標。然後我們看看class:

typedef struct objc_property *objc_property_t;

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。

注意:所有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中的函式指標跳轉到對應的函式中去執行。

iOS開發Runtime那點事

runtime從字面上的意思理解就是執行時間,run 跑,執行 time 時間 在ios中呢俗稱執行時,它是一套底層的純c語言api,屬於乙個c語言庫,包含了很多底層的c語言api,同時它也是oc的幕後工作者,我們平時寫的oc 在執行的過程中都會轉為runtime的c語言 注意哦 用到runtime...

iOS開發那些事 如何編譯iOS程式

我們從編寫到發布應用會經歷3個階段 模擬器上執行除錯 裝置上執行除錯和發布編譯,蘋果為了防止非法裝置和非開發人員除錯和發布應用,使用配置概要檔案 provisioningprofiles 控制在裝置上執行除錯和發布編譯階段,配置概要檔案分為兩種 開發配置概要檔案和發布配置概要檔案 1 建立發布配置概...

iOS開發那些事 如何編譯iOS程式

我們從編寫到發布應用會經歷3個階段 模擬器上執行除錯 裝置上執行除錯和發布編譯,蘋果為了防止非法裝置和非開發人員除錯和發布應用,使用配置概要檔案 provisioning profiles 控制在裝置上執行除錯和發布編譯階段,配置概要檔案分為兩種 開發配置概要檔案和發布配置概要檔案 1 建立發布配置...