Runtime機制之結構體及操做函數

1、動態語言

Objective-C語言是一門動態語言,它將不少靜態語言在編譯和連接時期作的事放到了運行時來處理。這種動態語言的優點在於:具備靈活性,好比:消息轉發,方法交換等。它有一個運行時系統Objc Runtime,實際上是一個Runtime庫,基本上是用C和彙編寫的,這個庫使得C語言有了面向對象的能力。數組

1. runtime庫主要作下面兩件事:

  • 封裝:用c語言把對象封裝成基本的數據結構,如:類結構體,對象結構體等。這些結構體和函數被runtime函數封裝後,咱們就能夠在程序運行時建立,檢查,修改類、對象和它們的方法了。
  • 找出方法的最終執行代碼:把消息機制轉換爲函數的調用。

 

2、基本結構體

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鏈表中

 

3、類與對象操做函數

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 );

 

4、動態建立類和對象 

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 );

 

 

5、獲取類定義

 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 );
相關文章
相關標籤/搜索