一、Objective-C Runtime到底是什么東西忿檩?
簡而言之尉尾,Objective-C Runtime是一個將C語言轉(zhuǎn)化為面向?qū)ο笳Z言的擴(kuò)展。
我們將C++和Objective進(jìn)行對比燥透,雖然C++和Objective-C都是在C的基礎(chǔ)上加入面向?qū)ο蟮奶匦詳U(kuò)充而成的程序設(shè)計語言沙咏,但二者實現(xiàn)的機(jī)制差異很大。C++是基于靜態(tài)類型班套,而Objective-C是基于動態(tài)運行時類型肢藐。也就是說用C++編寫的程序編譯時就直接編譯成了可令機(jī)器讀懂的機(jī)器語言;用Objective-C編寫的程序不能直接編譯成可令機(jī)器讀懂的機(jī)器語言吱韭,而是在程序運行的時候吆豹,通過Runtime把程序轉(zhuǎn)為可令機(jī)器讀懂的機(jī)器語言。也就是說用C++編寫的程序通過編譯器直接把函數(shù)地址硬編碼進(jìn)入可執(zhí)行文件理盆;而Objective-C無法通過編譯器直接把函數(shù)地址硬編碼進(jìn)入可執(zhí)行文件痘煤,而是在程序運行的時候,利用Runtime根據(jù)條件判斷作出決定猿规。函數(shù)標(biāo)識與函數(shù)過程的真正內(nèi)容之間的關(guān)聯(lián)可以動態(tài)修改衷快。Runtime是Objective不可缺少的重要一部分。
Demo傳送門-> runtime源碼
二姨俩、Objective-C的元素認(rèn)知
2.1 id和Class
打開/Public Headers/objc.h文件可以看到如下定義:
#if!OBJC_TYPES_DEFINED/// An opaque type that represents an Objective-C class.typedefstructobjc_class*Class;/// Represents an instance of a class.structobjc_object{Class isa? OBJC_ISA_AVAILABILITY;};/// A pointer to an instance of a class.typedefstructobjc_object*id;#endif
Class是一個指向objc_class結(jié)構(gòu)體的指針蘸拔,而id是一個指向objc_object結(jié)構(gòu)體的指針,其中的isa是一個指向objc_class結(jié)構(gòu)體的指針环葵。其中的id就是我們所說的對象调窍,Class就是我們所說的類。
打開/Public Headers/runtime.h文件
objc_class的定義如下:
typedef struct objc_class *Class;
structobjc_class{
Class isa? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC_ISA_AVAILABILITY;// metaclass
#if!__OBJC2__
Class super_class? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 父類
constchar*name? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 類名
long version? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 類的版本信息张遭,默認(rèn)為0邓萨,可以通過runtime函數(shù)class_setVersion或者class_getVersion進(jìn)行修改、讀取
long info? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 類信息,供運行時期使用的一些位標(biāo)識先誉,如CLS_CLASS (0x1L) 表示該類為普通 class,其中包含實例方法和變量;CLS_META (0x2L) 表示該類為 metaclass的烁,其中包含類方法;
long instance_size? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 該類的實例變量大泻侄(包括從父類繼承下來的實例變量)
struct objc_ivar_list*ivars? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 該類的成員變量地址列表
struct objc_method_list**methodLists? ? OBJC2_UNAVAILABLE;// 方法地址列表,與 info 的一些標(biāo)志位有關(guān)渴庆,如CLS_CLASS (0x1L)铃芦,則存儲實例方法,如CLS_META (0x2L)襟雷,則存儲類方法;
struct objc_cache*cache? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 緩存最近使用的方法地址刃滓,用于提升效率;
struct objc_protocol_list*protocols? ? ? OBJC2_UNAVAILABLE;// 存儲該類聲明遵守的協(xié)議的列表
#endif
}
/* Use `Class` instead of `struct objc_class *` */
由以上代碼可見耸弄,類與對象的區(qū)別就是類比對象多了很多特征成員咧虎,?類也可以當(dāng)做一個objc_object來對待,也就是說類和對象都是對象计呈,分別稱作類對象(class object)和實例對象(instance object)砰诵,這樣我們就可以區(qū)別對象和類了。
isa:objc_object(實例對象)中isa指針指向的類結(jié)構(gòu)稱為class(也就是該對象所屬的類)其中存放著普通成員變量與動態(tài)方法(“-”開頭的方法)捌显;此處isa指針指向的類結(jié)構(gòu)稱為metaclass茁彭,其中存放著static類型的成員變量與static類型的方法(“+”開頭的方法)。
super_class: 指向該類的父類的指針扶歪,如果該類是根類(如NSObject或NSProxy)理肺,那么super_class就為nil。
類與對象的繼承層次關(guān)系如圖(圖片源自網(wǎng)絡(luò)):
所有的metaclass中isa指針都是指向根metaclass善镰,而根metaclass則指向自身妹萨。根metaclass是通過繼承根類產(chǎn)生的,與根class結(jié)構(gòu)體成員一致炫欺,不同的是根metaclass的isa指針指向自身眠副。
2.2 SEL
SEL是selector在Objective-C中的表示類型。selector可以理解為區(qū)別方法的ID竣稽。
typedef struct objc_selector *SEL;
objc_selector的定義如下:
struct objc_selector{
char*name;OBJC2_UNAVAILABLE;// 名稱
char*types;OBJC2_UNAVAILABLE;// 類型
};
name和types都是char類型囱怕。
2.3 IMP
終于到IMP了,它在objc.h中得定義如下:
typedef id(*IMP)(id,SEL,...);
IMP是“implementation”的縮寫毫别,它是由編譯器生成的一個函數(shù)指針娃弓。當(dāng)你發(fā)起一個消息后(下文介紹),這個函數(shù)指針決定了最終執(zhí)行哪段代碼岛宦。
2.4 Method
Method代表類中的某個方法的類型台丛。
typedef struct objc_method *Method;
objc_method的定義如下:
struct objc_method{
SEL method_name? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 方法名
char*method_types? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 方法類型
IMP method_imp? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 方法實現(xiàn)
}
方法名method_name類型為SEL,上文提到過。
方法類型method_types是一個char指針挽霉,存儲著方法的參數(shù)類型和返回值類型防嗡。
方法實現(xiàn)method_imp的類型為IMP,上文提到過侠坎。
2.5 Ivar
Ivar代表類中實例變量的類型
typedef struct objc_ivar *Ivar;
objc_ivar的定義如下:
struct objc_ivar{
char*ivar_name? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 變量名
char*ivar_type? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 變量類型
intivar_offset? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// ?基地址偏移字節(jié)
#ifdef __LP64__
? ?intspace? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 占用空間
#endif
}
2.6 objc_property_t
objc_property_t是屬性蚁趁,它的定義如下:
typedef struct objc_property *objc_property_t;
objc_property是內(nèi)置的類型,與之關(guān)聯(lián)的還有一個objc_property_attribute_t实胸,它是屬性的attribute他嫡,也就是其實是對屬性的詳細(xì)描述,包括屬性名稱庐完、屬性編碼類型钢属、原子類型/非原子類型等。它的定義如下:
typedef struct{
constchar*name;// 名稱
constchar*value;// 值(通常是空的)
}objc_property_attribute_t;
2.7 Cache
Catch的定義如下:
typedef struct objc_cache *Cache
objc_cache的定義如下:
struct objc_cache{
unsigned int mask? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;
unsigned int occupied ? ? ? ? ? OBJC2_UNAVAILABLE;
Method buckets[1] ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;
};
mask: 指定分配cache buckets的總數(shù)门躯。在方法查找中淆党,Runtime使用這個字段確定數(shù)組的索引位置。
occupied: 實際占用cache buckets的總數(shù)讶凉。
buckets: 指定Method數(shù)據(jù)結(jié)構(gòu)指針的數(shù)組宁否。這個數(shù)組可能包含不超過mask+1個元素。需要注意的是缀遍,指針可能是NULL慕匠,表示這個緩存bucket沒有被占用,另外被占用的bucket可能是不連續(xù)的域醇。這個數(shù)組可能會隨著時間而增長台谊。
objc_msgSend(下文講解)每調(diào)用一次方法后,就會把該方法緩存到cache列表中譬挚,下次的時候锅铅,就直接優(yōu)先從cache列表中尋找,如果cache沒有减宣,才從methodLists中查找方法盐须。
2.8 Catagory
這個就是我們平時所說的類別了,很熟悉吧漆腌。它可以動態(tài)的為已存在的類添加新的方法贼邓。
它的定義如下:
typedef struct objc_category *Category;
objc_category的定義如下:
struct objc_category{
char*category_name? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 類別名稱char*class_name? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;// 類名
struct objc_method_list*instance_methods? ? OBJC2_UNAVAILABLE;// 實例方法列表
struct objc_method_list*class_methods? ? ? ? OBJC2_UNAVAILABLE;// 類方法列表struct objc_protocol_list*protocols? ? ? ? ? OBJC2_UNAVAILABLE;// 協(xié)議列表
}
因為是入門,以上就列舉這些吧闷尿!