類的本質
數據結構: 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指向的方法。找到后即運行這個方法。
上圖是關于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 );