Runtime - 類與屬性

類的本質

數據結構: 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;
數據類型:

isa和super_class :不同的類中可以有相同的方法(同一個類的方法不能同名,哪怕參數類型不同,后面解釋...),所以要先確定是那個類。isa和super_class是找到實現函數的關鍵映射,決定找到存放在哪個類的方法實現。(isa用于自省確定所屬類,super_class確定繼承關系)。

實例對象的isa指針指向類,類的isa指針指向其元類(metaClass)。對象就是一個含isa指針的結構體。類存儲實例對象的方法列表,元類存儲類的方法列表,元類也是類對象。
這是id類型的結構(類似于C里面的void *):

struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};
typedef struct objc_object *id;

當創建實例對象時,分配的內存包含一個objc_object數據結構,然后是類到父類直到根類NSObject的實例變量的數據。NSObject類的alloc和allocWithZone:方法使用函數class_createInstance來創建objc_object數據結構。

向一個Objective-C對象發送消息時,運行時庫會根據實例對象的isa指針找到這個實例對象所屬的類。Runtime庫會在類的方法列表由super_class指針找到父類的方法列表直至根類NSObject中去尋找與消息對應的selector指向的方法。找到后即運行這個方法。

Class isa and superclass relationship.png

上圖是關于isa和super_class指針的圖解:

1、isa:實例對象->類->元類->(不經過父元類)直接到根元類(NSObject的元類),根元類的isa指向自己;
2、 superclass:類->父類->...->根類NSObject,元類->父元類->...->根元類->根類,NSObject的superclass指向nil。

操作函數:

類對象以class_為前綴,實例對象以object_為前綴
<li>class:</li>
get: 類名,父類,元類;實例變量,成員變量;屬性;實例方法,類方法,方法實現;

// 獲取類的類名
const char * class_getName ( Class cls );
// 獲取類的父類
Class class_getSuperclass ( Class cls );

// 獲取實例大小
size_t class_getInstanceSize ( Class cls );
// 獲取類中指定名稱實例成員變量的信息
Ivar class_getInstanceVariable ( Class cls, const char *name );
// 獲取類成員變量的信息
Ivar class_getClassVariable ( Class cls, const char *name );
// 獲取指定的屬性
objc_property_t class_getProperty ( Class cls, const char *name );

// 獲取實例方法
Method class_getInstanceMethod ( Class cls, SEL name );
// 獲取類方法
Method class_getClassMethod ( Class cls, SEL name );
// 獲取方法的具體實現
IMP class_getMethodImplementation ( Class cls, SEL name );
IMP class_getMethodImplementation_stret ( Class cls, SEL name );

copy: 成員變量列表;屬性列表;方法列表;協議列表;

// 獲取整個成員變量列表
Ivar * class_copyIvarList ( Class cls, unsigned int *outCount );
// 獲取屬性列表
objc_property_t * class_copyPropertyList ( Class cls, unsigned int *outCount );
// 獲取所有方法的列表
Method * class_copyMethodList ( Class cls, unsigned int *outCount );
// 獲取類實現的協議列表
Protocol * class_copyProtocolList ( Class cls, unsigned int *outCount );

add: 成員變量;屬性;方法;協議;(添加成員變量只能在運行時創建的類,且不能為元類)

// 添加成員變量
BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char *types );
// 添加屬性
BOOL class_addProperty ( 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 );
// 添加協議
BOOL class_addProtocol ( Class cls, Protocol *protocol );

replace:屬性;方法;

// 替換類的屬性
void class_replaceProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );
// 替代方法的實現
IMP class_replaceMethod ( Class cls, SEL name, IMP imp, const char *types );

respond:響應方法判斷(內省)

// 類實例是否響應指定的selector
BOOL class_respondsToSelector ( Class cls, SEL sel );

isMetaClass:元類判斷(內省)

// 判斷給定的Class是否是一個元類
BOOL class_isMetaClass ( Class cls );

conform:遵循協議判斷(內?。?/p>

// 返回類是否實現指定的協議
BOOL class_conformsToProtocol ( Class cls, Protocol *protocol );

<li>objc_:</li>
get: 實例變量;成員變量;類名;類;元類;關聯對象

// 獲取對象實例變量
Ivar object_getInstanceVariable ( id obj, const char *name, void **outValue );
// 獲取對象中實例變量的值
id object_getIvar ( id obj, Ivar ivar );
// 獲取對象的類名
const char * object_getClassName ( id obj );
// 獲取對象的類
Class object_getClass ( id obj );
Class objc_getClass ( const char *name );
// 返回指定類的元類
Class objc_getMetaClass ( const char *name );
//獲取關聯對象
id objc_getAssociatedObject(self, &myKey);

copy:對象;類;類列表;協議列表;

// 獲取指定對象的一份拷貝
id object_copy ( id obj, size_t size );
// 創建并返回一個指向所有已注冊類的指針列表
Class * objc_copyClassList ( unsigned int *outCount );

set: 實例變量;類;類列表;協議;關聯對象;

// 設置類實例的實例變量的值
Ivar object_setInstanceVariable ( id obj, const char *name, void *value );
// 設置對象中實例變量的值
void object_setIvar ( id obj, Ivar ivar, id value );
//設置關聯對象
void objc_setAssociatedObject(self, &myKey, anObject, OBJC_ASSOCIATION_RETAIN);

dispose: 對象;

// 釋放指定對象占用的內存
id object_dispose ( id obj );

<li>動態創建/銷毀類、對象</li>
動態創建/銷毀類:

// 創建一個新類和元類
Class objc_allocateClassPair ( Class superclass, const char *name, size_t extraBytes );

// 銷毀一個類及其相關聯的類
void objc_disposeClassPair ( Class cls );

// 在應用中注冊由objc_allocateClassPair創建的類
void objc_registerClassPair ( Class cls );

動態創建/銷毀對象:

// 創建類實例
id class_createInstance ( Class cls, size_t extraBytes );

// 在指定位置創建類實例
id objc_constructInstance ( Class cls, void *bytes );

// 銷毀類實例
void * objc_destructInstance ( id obj );

實例變量、屬性相關:

實例變量和屬性也是類對象的關鍵配置。
屬性變量的意義就是方便讓其他對象訪問實例變量,另外可以拓展實例變量的作用范圍。當然,你可以設置只讀或者可寫等,設置方法也可自定義。

數據類型:

Ivar;

typedef struct objc_ivar *Ivar;

struct objc_ivar {
    char *ivar_name                 OBJC2_UNAVAILABLE;  // 變量名
    char *ivar_type                 OBJC2_UNAVAILABLE;  // 變量類型
    int ivar_offset                 OBJC2_UNAVAILABLE;  // 基地址偏移字節
#ifdef __LP64__
    int space                       OBJC2_UNAVAILABLE;
#endif
}

objc_property_t(取名可能是因為當時Objective-C1.0還沒屬性);

typedef struct objc_property *objc_property_t;

objc_property_attribute_t(屬性的特性有:返回值、是否為atomic、getter/setter名字、是否為dynamic、背后使用的ivar名字、是否為弱引用等);

typedef struct {
    const char *name;           // 特性名
    const char *value;          // 特性值
} objc_property_attribute_t;
操作函數:

<li>ivar_:</li>
get:

// 獲取成員變量名
const char * ivar_getName ( Ivar v );

// 獲取成員變量類型編碼
const char * ivar_getTypeEncoding ( Ivar v );

// 獲取成員變量的偏移量
ptrdiff_t ivar_getOffset ( Ivar v );

<li>property_:</li>

// 獲取屬性名
const char * property_getName ( objc_property_t property );

// 獲取屬性特性描述字符串
const char * property_getAttributes ( objc_property_t property );

// 獲取屬性中指定的特性
char * property_copyAttributeValue ( objc_property_t property, const char *attributeName );

// 獲取屬性的特性列表
objc_property_attribute_t * property_copyAttributeList ( objc_property_t property, unsigned int *outCount );
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容