Runtime介紹html
Objective-C語言是一門動態語言,它將不少靜態語言在編譯和連接時期作的事放到了運行時來處理。這意味着它不只須要一個編譯器,也須要一個運行時系統來動態得建立類和對象、進行消息傳遞和轉發。這個運行時系統即Objc Runtime。Objc Runtime實際上是一個Runtime庫,它基本上是用C和彙編寫的,這個庫使得C語言有了面向對象的能力。數組
Runtime庫主要作下面幾件事:緩存
封裝
:在這個庫中,對象能夠用C語言中的結構體表示,而方法能夠用C函數 來實現,另外再加上了一些額外的特性。這些結構體和函數被runtime函數封裝後,咱們就能夠在程序運行時建立,檢查,修改類、對象和它們的方法了。消息傳遞
:當程序執行[object doSomething]時,會向消息接收者(object)發送一條消息(doSomething),runtime會根據消息接收者是否能響應該消息而作出不一樣的反應。這將在後面詳細介紹。在接下來的一系列文章中,我將介紹一下runtime
的基本工做原理以及在咱們的代碼裏能夠用它來作什麼。在本文中,咱們先來了解一下類與對象。bash
###OC對象 OC的對象主要能夠分爲三種:數據結構
instance對象 它主要是經過類alloc出來的對象,每次調用alloc都會產生新的instance對象。app
NSObjcet *object1 = [[NSObjcet alloc] init];
複製代碼
instance對象
在內存中存儲的信息包括:ide
class對象 咱們經過class方法或runtime方法獲得一個class對象。class對象也就是類對象。==每個類在內存中有且只有一個class對象==。函數
Class objectClass1 = [NSObject class];
// runtime
Class objectClass2 = object_getClass(object1);
複製代碼
class對象
在內存中存儲的信息主要包括:性能
meta-class對象 咱們經過runtime方法獲得一個class對象。==每一個類在內存中有且只有一個meta-class對象。==ui
//runtime中傳入類對象此時獲得的就是元類對象
Class objectMetaClass = object_getClass([NSObject class]);
// 判斷該對象是否爲元類對象
class_isMetaClass(objectMetaClass)
複製代碼
meta-class對象
在內存中存儲的信息主要包括:
咱們來看看下面的圖,來分析這三者的關係
從上圖中,咱們能夠分析出:
###Class
Objective-C類是由Class
類型來表示的,它其實是一個指向objc_class
結構體的指針。在objc/objc.h
它的定義以下:
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
複製代碼
在objc/runtime.h
中咱們能夠看到結構體objc_class
的定義以下:
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class _Nullable super_class OBJC2_UNAVAILABLE;// 父類
const char * _Nonnull name OBJC2_UNAVAILABLE;// 類名
long version OBJC2_UNAVAILABLE;// 類的版本信息,默認爲0
long info OBJC2_UNAVAILABLE;// 類信息,供運行期使用的一些位標識
long instance_size OBJC2_UNAVAILABLE;// 該類的實例變量大小
struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE;//該類的成員變量鏈表
struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE;// 方法定義的鏈表
struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE;// 方法緩存
struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE;// 協議鏈表
#endif
} OBJC2_UNAVAILABLE;
複製代碼
###1. name 類名
// 獲取類的類名
const char * class_getName ( Class cls );
複製代碼
###2. isa 在Objective-C中,類自身也是一個對象,咱們稱之爲類對象,在這個類對象中,也有一個isa指針
,它指向了metaClass(元類)
。
###3. super_class 指向該類的父類,若是該類已是最頂層的根類(如NSObject或NSProxy),則super_class
爲nil。
###4. instance_size
// 獲取實例大小
size_t class_getInstanceSize ( Class cls );
複製代碼
###5. objc_ivar_list 成員變量和屬性信息。ivars是一個數組,全部的成員變量、屬性的信息是放在鏈表ivars中的。
######獲取成員變量信息
// 獲取整個成員變量列表
Ivar * class_copyIvarList ( Class cls, unsigned int *outCount );
//獲取一個成員變量的名字
const char * _Nullable ivar_getName(Ivar _Nonnull v)
//獲取一個成員變量的
const char * _Nullable ivar_getTypeEncoding(Ivar _Nonnull v)
複製代碼
ivar_getTypeEncoding
函數獲取的是變量的數據類型,詳細的說明能夠看蘋果官方文檔Type Encodingsclass_copyIvarLis
t函數,它返回一個指向成員變量信息的數組。這個數組不包含在父類中聲明的變量。outCount指針返回數組的大小。須要注意的是,咱們必須使用free()
來釋放這個數組。######獲取成員變量屬性信息
/// An opaque type that represents an Objective-C declared property.
typedef struct objc_property *objc_property_t;
//獲取整個成員變量屬性列表
objc_property_t _Nonnull *_Nullable class_copyPropertyList(Class _Nullable cls, unsigned int * _Nullable outCount)
/// Defines a property attribute
typedef struct {
const char * _Nonnull name; /**< The name of the attribute */
const char * _Nonnull value; /**< The value of the attribute (usually empty) */
} objc_property_attribute_t;
objc_property_attribute_t * _Nullable property_copyAttributeList(objc_property_t _Nonnull property,unsigned int * _Nullable outCount)
複製代碼
objc_property_attribute_t
實際上是對屬性的詳細描述,包括屬性名稱、屬性編碼類型、原子類型/非原子類型等。如T@"NSString",C,N,V_title
,TQ,N,V_age
。下面詳細地說明property_getAttributes
獲取到的屬性的語義:
屬性的詳細說明Property Type
###6. methodLists 對象方法列表。
/// An opaque type that represents a method in a class definition.
typedef struct objc_method *Method;
struct objc_method {
SEL method_name; // 方法名稱
char *method_typesE; // 參數和返回類型的描述字串
IMP method_imp; // 方法的具體的實現的指針
}
複製代碼
獲取method
信息:
//方法列表
Method _Nonnull * _Nullable class_copyMethodList(Class _Nullable cls, unsigned int * _Nullable outCount)
//方法名
SEL _Nonnull method_getName(Method _Nonnull m)
//方法實現
IMP _Nonnull method_getImplementation(Method _Nonnull m)
//方法參數和返回類型的信息
const char * _Nullable method_getTypeEncoding(Method _Nonnull m)
//方法參數數量
unsigned int method_getNumberOfArguments(Method _Nonnull m)
//方法參數類型
char * _Nullable method_copyArgumentType(Method _Nonnull m, unsigned int index)
複製代碼
method_getTypeEncoding
獲取函數的編碼,其結果是一串值,如:v16@0:8;@16@0:8;v24@0:8@16。這些字符串是什麼意思,經過蘋果官方文檔咱們能夠分析出:
###7. cache 用於緩存最近使用的方法。一個接收者對象接收到一個消息時,它會根據isa指針
去查找可以響應這個消息的對象。在實際使用中,這個對象只有一部分方法是經常使用的,不少方法其實不多用或者根本用不上。這種狀況下,若是每次消息來時,咱們都是methodLists
中遍歷一遍,性能勢必不好。這時,cache
就派上用場了。在咱們每次調用過一個方法後,這個方法就會被緩存到cache
列表中,下次調用的時候runtime就會優先去cache
中查找,若是cache
沒有,纔去methodLists
中查找方法。這樣,對於那些常常用到的方法的調用,但提升了調用的效率。
參考: