一、動態語言 Objective-C語言是一門動態語言,它將很多靜態語言在編譯和鏈接時期做的事放到了運行時來處理。這種動態語言的優勢在於:具有靈活性,比如:消息轉發,方法交換等。它有一個運行時系統Objc Runtime,其實是一個Runtime庫,基本上是用C和彙編寫的,這個庫使得C語言有了面向對 ...
一、動態語言
Objective-C語言是一門動態語言,它將很多靜態語言在編譯和鏈接時期做的事放到了運行時來處理。這種動態語言的優勢在於:具有靈活性,比如:消息轉發,方法交換等。它有一個運行時系統Objc Runtime,其實是一個Runtime庫,基本上是用C和彙編寫的,這個庫使得C語言有了面向對象的能力。
1. runtime庫主要做下麵兩件事:
- 封裝:用c語言把對象封裝成基本的數據結構,如:類結構體,對象結構體等。這些結構體和函數被runtime函數封裝後,我們就可以在程式運行時創建,檢查,修改類、對象和它們的方法了。
- 找出方法的最終執行代碼:把消息機制轉換為函數的調用。
二、基本結構體
1. 類結構體:objc_class
- isa:指向該類對象所屬類(即元類)的指針,根類的元類指向自己
- super_class:指向父類的指針,根類的父類指針指向NULL
- name:類名
- version:版本
- info:類信息
- instance_size:改類實例的大小
- ivars:屬性鏈表
- methodLists:方法鏈表
- cache:方法緩存鏈表
- protocols:協議鏈表
typedef struct objc_class *Class;
struct objc_class { Class isa OBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class super_class OBJC2_UNAVAILABLE; // 父類 const char *name OBJC2_UNAVAILABLE; // 類名 long version OBJC2_UNAVAILABLE; // 類的版本信息,預設為0 long info OBJC2_UNAVAILABLE; // 類信息,供運行期使用的一些位標識 long instance_size OBJC2_UNAVAILABLE; // 該類的實例變數大小 struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 該類的成員變數鏈表 struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定義的鏈表 struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法緩存 struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 協議鏈表 #endif } OBJC2_UNAVAILABLE;
2. 實例對象結構體:objc_objective
- isa:指向所屬類的指針。(僅僅一個指針)
typedef struct objc_object *id; struct objc_object { Class isa OBJC_ISA_AVAILABILITY; };
3. 緩存方法鏈表結構體:objc_cache
- mask:可緩存方法的數量
- occupied:已緩存方法的數量
- buckets:指針數組,存儲的是指針,指向已緩存的方法結構體
typedef struct objc_cache *cache; struct objc_cache { unsigned int mask /* total = mask + 1 */ OBJC2_UNAVAILABLE; unsigned int occupied OBJC2_UNAVAILABLE; Method buckets[1] OBJC2_UNAVAILABLE; };
4. 元類結構體(類對象所屬類)
- 同類結構體一樣,只是元類的isa指針都是指向根類NSObject元類,而根類的元類的isa指針指向自己。
我們都知道,實例對象擁有一個指向所屬類的isa指針。那類本身也可以看成是所屬類的對象,即類對象那它自然也擁有一個指向所屬類的isa指針,這個指針指向的也是該類對象的所屬類,即元類。所以,當我們向一個對象發送消息時,runtime會在這個對象所屬的這個類的方法列表中查找方法;而向一個類發送消息時,會在這個類的所屬類,即元類meta-class的方法列表中查找。
5. 舉例說明,看看以下代碼如何執行的
NSArray *array = [[NSArray alloc] init];
- runtime庫向類對象NSArray發送了alloc消息,類對象根據isa指針去所屬類,即元類中查找響應的方法
- 在元類中,先查cache,再查methodLists,由於元類中沒有方法alloc,便根據super_class指針去父類NSObjec中找查找
- 在父類中,同樣先查cache,再查methodLists,在methodLists找到,立即響應消息
- 檢測類NSArray中instance_size的大小,根據所需的空間大小分配記憶體
- 創建objc_objective結構體以及實例變數,把結構體的isa指針指向父類
- 把alloc方法緩存到自己的cache鏈表中
- runtime庫又向剛創建好的實例對象發送init消息,對象根據isa指針去所屬類NSArray中查找
- 先查cache,再查methodLists,查到後則響應
- 把實例對象中的實例變數初始化
- 把方法init緩存到cache鏈表中
三、類與對象操作函數
1. 類相關操作函數:以class為首碼命名
- class_getName // 獲取類名
- class_getSuperclass // 獲取父類
- class_isMetaClass // 判斷類是不是元類
- class_getInstanceSize // 獲取實例大小
- class_getInstanceVariable // 獲取實例成員變數
- class_getClassVariable // 獲取類成員變數
- class_addIvar // 添加實例變數
- class_copyIvarList // 獲取整個成員變數表
- class_getProperty // 獲取指定屬性
- class_copyPropertyList // 獲取整個屬性表
- class_addProperty // 添加屬性
- class_replaceProperty // 替換屬性
- class_addMethod // 添加方法
- class_getInstanceMethod // 獲取實例方法
- class_getClassMethod // 獲取類方法
- class_copyMethodList // 獲取所有方法的數組
- class_replaceMethod // 替代方法的實現
- class_getMethodImplementation // 返回方法的具體實現
- class_respondsToSelector // 類實例是否響應指定的selector
- class_addProtocol // 添加協議
- class_conformsToProtocol // 返回類是否實現指定的協議
- class_copyProtocolList // 返回類實現的協議列表
- class_getVersion // 獲取版本號
- class_setVersion // 設置版本號
-
父類和元類
// 獲取類的父類 Class class_getSuperclass ( Class cls ); // 判斷給定的Class是否是一個元類 BOOL class_isMetaClass ( Class cls );
-
-
類名
-
// 獲取類的類名 const char * class_getName ( Class cls );
-
-
成員變數大小
-
// 獲取實例大小 size_t class_getInstanceSize ( Class cls );
-
-
版本
-
// 獲取版本號 int class_getVersion ( Class cls ); // 設置版本號 void class_setVersion ( Class cls, int version );
-
-
成員變數
-
/** 成員變數操作函數 */
// 獲取類中指定名稱實例成員變數的信息 Ivar class_getInstanceVariable ( Class cls, const char *name ); // 獲取類成員變數的信息 Ivar class_getClassVariable ( Class cls, const char *name ); // 添加成員變數 BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char *types ); // 獲取整個成員變數列表 Ivar * class_copyIvarList ( Class cls, unsigned int *outCount );
-
-
屬性
-
/** 屬性操作函數 */ // 獲取指定的屬性 objc_property_t class_getProperty ( Class cls, const char *name ); // 獲取屬性列表 objc_property_t * class_copyPropertyList ( Class cls, unsigned int *outCount ); // 為類添加屬性 BOOL class_addProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount ); // 替換類的屬性 void class_replaceProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );
-
-
方法
-
// 添加方法 BOOL class_addMethod ( Class cls, SEL name, IMP imp, const char *types ); // 獲取實例方法 Method class_getInstanceMethod ( Class cls, SEL name ); // 獲取類方法 Method class_getClassMethod ( Class cls, SEL name ); // 獲取所有方法的數組 Method * class_copyMethodList ( Class cls, unsigned int *outCount ); // 替代方法的實現 IMP class_replaceMethod ( Class cls, SEL name, IMP imp, const char *types ); // 返回方法的具體實現 IMP class_getMethodImplementation ( Class cls, SEL name ); IMP class_getMethodImplementation_stret ( Class cls, SEL name ); // 類實例是否響應指定的selector BOOL class_respondsToSelector ( Class cls, SEL sel );
-
-
協議
-
// 添加協議 BOOL class_addProtocol ( Class cls, Protocol *protocol ); // 返回類是否實現指定的協議 BOOL class_conformsToProtocol ( Class cls, Protocol *protocol ); // 返回類實現的協議列表 Protocol * class_copyProtocolList ( Class cls, unsigned int *outCount );
2. 對象相關的操作函數,以object為首碼命名
- object_copy // 返回指定對象的一份拷貝
- object_dispose // 釋放指定對象占用的記憶體
- object_setInstanceVariable // 修改類實例的實例變數的值
- object_getInstanceVariable // 獲取對象實例變數的值
- object_getIndexedIvars // 返回指向給定對象分配的任何額外位元組的指針
- object_getIvar // 返回對象中實例變數的值
- object_setIvar // 設置對象中實例變數的值
- object_getClassName // 返回給定對象的類名
- object_getClass // 返回對象的類
- object_setClass // 設置對象的類
-
-
針對整個對象進行操作的函數
-
// 返回指定對象的一份拷貝 id object_copy ( id obj, size_t size ); // 釋放指定對象占用的記憶體 id object_dispose ( id obj );
-
-
針對對象實例變數進行操作的函數
-
// 修改類實例的實例變數的值 Ivar object_setInstanceVariable ( id obj, const char *name, void *value ); // 獲取對象實例變數的值 Ivar object_getInstanceVariable ( id obj, const char *name, void **outValue ); // 返回指向給定對象分配的任何額外位元組的指針 void * object_getIndexedIvars ( id obj ); // 返回對象中實例變數的值 id object_getIvar ( id obj, Ivar ivar ); // 設置對象中實例變數的值 void object_setIvar ( id obj, Ivar ivar, id value );
-
-
針對對象的類進行操作的函數
-
// 返回給定對象的類名 const char * object_getClassName ( id obj ); // 返回對象的類 Class object_getClass ( id obj ); // 設置對象的類 Class object_setClass ( id obj, Class cls );
四、動態創建類和對象
1. 動態創建類
- objc_allocateClassPair // 創建一個新類和元類
- objc_disposeClassPair // 銷毀一個類及其相關聯的類
- objc_registerClassPair // 在應用中註冊由objc_allocateClassPair創建的類
// 創建一個新類和元類 Class objc_allocateClassPair ( Class superclass, const char *name, size_t extraBytes ); // 銷毀一個類及其相關聯的類 void objc_disposeClassPair ( Class cls ); // 在應用中註冊由objc_allocateClassPair創建的類 void objc_registerClassPair ( Class cls );
2. 動態創建對象
- class_createInstance // 創建類實例
- objc_constructInstance // 在指定位置創建類實例
- objc_destructInstance // 銷毀類實例
// 創建類實例 id class_createInstance ( Class cls, size_t extraBytes ); // 在指定位置創建類實例 id objc_constructInstance ( Class cls, void *bytes ); // 銷毀類實例 void * objc_destructInstance ( id obj );
五、獲取類定義
1. Objective-C動態運行庫會自動註冊我們代碼中定義的所有的類。我們也可以在運行時創建類定義並使用objc_addClass函數來註冊它們。
// 獲取已註冊的類定義的列表 int objc_getClassList ( Class *buffer, int bufferCount ); // 創建並返回一個指向所有已註冊類的指針列表 Class * objc_copyClassList ( unsigned int *outCount ); // 返回指定類的類定義 Class objc_lookUpClass ( const char *name ); Class objc_getClass ( const char *name ); Class objc_getRequiredClass ( const char *name ); // 返回指定類的元類 Class objc_getMetaClass ( const char *name );