一遣鼓、類(lèi)的數(shù)據(jù)結(jié)構(gòu)
Class(指針)
typedef struct objc_class *Class;
/*
這是由編譯器為每個(gè)類(lèi)產(chǎn)生的數(shù)據(jù)結(jié)構(gòu),這個(gè)結(jié)構(gòu)定義了一個(gè)類(lèi).這個(gè)結(jié)構(gòu)是通過(guò)編譯器在執(zhí)行時(shí)產(chǎn)生,在運(yùn)行時(shí)發(fā)送消息時(shí)使用.因此,一些成員改變了類(lèi)型.編譯器產(chǎn)生"char* const"類(lèi)型的字符串指針替代了下面的成員變量"super_class"
*/
struct objc_class {
struct objc_class*? class_pointer;? ? /* 指向元類(lèi)的指針. */
struct objc_class*? super_class;? ? ? /* 指向父類(lèi)的指針. 對(duì)于NSObject來(lái)說(shuō)是NULL.*/
const char*? ? ? ? name;? ? ? ? ? ? /* 類(lèi)的名稱(chēng). */
long? ? ? ? ? ? ? ? version;? ? ? ? ? /* 未知. */
unsigned long? ? ? info;? ? ? ? ? ? /* 比特蒙板.? 參考下面類(lèi)的蒙板定義. */
long? ? ? ? ? ? ? ? instance_size;? ? /* 類(lèi)的字節(jié)數(shù).包含類(lèi)的定義和所有父類(lèi)的定義 */
#ifdef _WIN64
long pad;
#endif
struct objc_ivar_list* ivars;? ? ? ? /* 指向類(lèi)中定義的實(shí)例變量的列表結(jié)構(gòu). NULL代表沒(méi)有實(shí)例變量.不包括父類(lèi)的變量. */
struct objc_method_list*? methods;? ? /* 鏈接類(lèi)中定義的實(shí)例方法. */
struct sarray *? ? dtable;? ? ? ? ? ? /* 指向?qū)嵗椒ǚ峙浔? */
struct objc_class* subclass_list;? ? /* 父類(lèi)列表 */
struct objc_class* sibling_class;
struct objc_protocol_list *protocols; /* 要實(shí)現(xiàn)的原型列表 */
void* gc_object_type;
};
Method(指針)
typedef struct objc_method *Method;
/* 編譯器依據(jù)類(lèi)中定義的方法為該類(lèi)產(chǎn)生一個(gè)或更多這種這種結(jié)構(gòu).
一個(gè)類(lèi)的實(shí)現(xiàn)可以分散在一個(gè)文件中不同部分,同時(shí)類(lèi)別可以分散在不同的模塊中.為了處理這個(gè)問(wèn)題,使用一個(gè)單獨(dú)的方法鏈表 */
struct objc_method
{
SEL? ? ? ? method_name;? /* 這個(gè)變量就是方法的名稱(chēng).編譯器使用在這里使用一個(gè)`char*`,當(dāng)一個(gè)方法被注冊(cè),名稱(chēng)在運(yùn)行時(shí)被使用真正的SEL替代? */
const char* method_types; /* 描述方法的參數(shù)列表. 在運(yùn)行時(shí)注冊(cè)選擇器時(shí)使用.那時(shí)候方法名就會(huì)包含方法的參數(shù)列表.*/
IMP? ? ? ? method_imp;? /* 方法執(zhí)行時(shí)候的地址. */
};
Ivar(指針)
typedef struct objc_ivar *Ivar;
/* 編譯器依據(jù)類(lèi)中定義的實(shí)例變量為該類(lèi)產(chǎn)生一個(gè)或更多這種這種結(jié)構(gòu)? */
struct objc_ivar
{
const char* ivar_name;? /* 類(lèi)中定義的變量名. */
const char* ivar_type;? /* 描述變量的類(lèi)型.調(diào)試時(shí)非常有用. */
int? ? ? ? ivar_offset; /* 實(shí)例結(jié)構(gòu)的基地址偏移字節(jié) */
};
Category(指針)
typedef struct objc_category *Category;
/* 編譯器為每個(gè)類(lèi)別產(chǎn)生一個(gè)這樣的結(jié)構(gòu).一個(gè)類(lèi)可以具有多個(gè)類(lèi)別同時(shí)既包括實(shí)例方法,也可以包括類(lèi)方法*/
struct objc_category
{
const char*? category_name;? ? ? ? ? ? ? ? /* 類(lèi)別名.定義在類(lèi)別后面的括號(hào)內(nèi)*/
const char*? class_name;? ? ? ? ? ? ? ? ? /* 類(lèi)名 */
struct objc_method_list? *instance_methods; /* 鏈接類(lèi)中定義的實(shí)例方法. NULL表示沒(méi)有實(shí)例方法. */
struct objc_method_list *class_methods;? ? /* 鏈接類(lèi)中定義的類(lèi)方法. NULL表示沒(méi)有類(lèi)方法. */
struct objc_protocol_list *protocols;? ? ? /* 遵循的協(xié)議表? */
};
objc_property_t
typedef struct objc_property *objc_property_t;
IMP
id (*IMP)(id, SEL, ...)
SEL
typedef struct objc_selector *SEL;
struct objc_selector
{
void *sel_id;
const char *sel_types;
};
objc_method_list
struct objc_method_list
{
struct objc_method_list*? method_next; /* 這個(gè)變量用來(lái)鏈接另一個(gè)單獨(dú)的方法鏈表 */
int? ? ? ? ? ? method_count;? ? ? ? ? ? /* 結(jié)構(gòu)中定義的方法數(shù)量 */
struct objc_method method_list[1];? ? ? /* 可變長(zhǎng)度的結(jié)構(gòu) */
};
objc_cache
struct objc_cache
{
unsigned int mask;
unsigned int occupied;
Method buckets[1];
};
objc_protocol_list
struct objc_protocol_list
{
struct objc_protocol_list *next;
size_t count;
struct objc_protocol *list[1];
};
二衔统、實(shí)例的數(shù)據(jù)結(jié)構(gòu)
id
typedef struct objc_object *id;
objc_object
struct objc_object
{
// 類(lèi)的指針是對(duì)象相關(guān)的類(lèi).如果是一個(gè)類(lèi)對(duì)象, 這個(gè)指針指向元類(lèi).
Class isa;
};
objc_super
struct objc_super
{
id? ? self;? ? ? ? /* 消息的接受者? */
Class super_class; /* 接受者的父類(lèi)? */
};
三、底層-Class詳解(iOS)
? iOS的開(kāi)發(fā)語(yǔ)言objective-c岛都,它的真實(shí)面目是它不是真正的面向?qū)ο笳Z(yǔ)言蚤认,而抽象理解為此而已凹蜈。其實(shí)它就是C+限寞,有個(gè)公式可以很好地詮釋那就是OC = C + Runtime;
? 接下來(lái)我們就好好講講在Runtime下的objc-class忍啸。
3.1Class定義
3.1.1 小小說(shuō)明一下objc-api.h里的OBJC_ISA_AVAILABILITY:
? /*介紹一下attribute((deprecated))的作用,__attribute是給函數(shù)、變量履植、類(lèi)做屬性說(shuō)明的關(guān)鍵字计雌,deprecated是棄用原先的進(jìn)行兼容
? 若是OBJC2,原先的類(lèi),編譯器發(fā)出警告*/
#if !defined(OBJC_ISA_AVAILABILITY)
#? if __OBJC2__
#? ? ? define OBJC_ISA_AVAILABILITY? __attribute__((deprecated))
#? else
#? ? ? define OBJC_ISA_AVAILABILITY? /* still available */
#? endif
#endif
typedef struct objc_method *Method;
typedef struct objc_ivar *Ivar;
typedef struct objc_category *Category;
typedef struct objc_property *objc_property_t;
3.1.2 接下來(lái)就是runtime.h里的Class的定義:
struct objc_class {
Class isa? OBJC_ISA_AVAILABILITY;//每個(gè)Class都有一個(gè)isa指針
#if !__OBJC2__
Class super_class? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;//父類(lèi)
const char *name? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;//類(lèi)名
long version? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;//類(lèi)版本
long info? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;//!*!供運(yùn)行期使用的一些位標(biāo)識(shí)玫霎。如:CLS_CLASS (0x1L)表示該類(lèi)為普通class; CLS_META(0x2L)表示該類(lèi)為metaclass等(runtime.h中有詳細(xì)列出)
long instance_size? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;//實(shí)例大小
struct objc_ivar_list *ivars? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;//存儲(chǔ)每個(gè)實(shí)例變量的內(nèi)存地址
struct objc_method_list **methodLists? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;//!*!根據(jù)info的信息確定是類(lèi)還是實(shí)例凿滤,運(yùn)行什么函數(shù)方法等
struct objc_cache *cache? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;//緩存
struct objc_protocol_list *protocols? ? ? ? ? ? ? ? ? ? OBJC2_UNAVAILABLE;//協(xié)議
#endif
} OBJC2_UNAVAILABLE;
四、class初始化
? Runtime的行為之一就是initialize庶近。在程序運(yùn)行過(guò)程中翁脆,它會(huì)在你程序中每個(gè)類(lèi)調(diào)用一次initialize。這個(gè)調(diào)用的時(shí)間發(fā)生在你的類(lèi)接收到消息之前鼻种,但是在它的超類(lèi)接收到initialize之后反番。
//在蘋(píng)果的官方Runtime中有個(gè)objc-initialize.m文件,進(jìn)行解讀
typedef struct _objc_initializing_classes {
int classesAllocated;//類(lèi)是否分配存在
Class *metaclasses;//類(lèi)的父類(lèi),如果沒(méi)有父類(lèi)那就是自身
}
_objc_initializing_classes;//初始化一個(gè)對(duì)象_objc_initializing_classes
//將所有的類(lèi)存儲(chǔ)在靜態(tài)鏈表中叉钥,以待接下來(lái)的接收和發(fā)送消息
static _objc_initializing_classes *_fetchInitializingClassList(BOOL create)
{
_objc_pthread_data *data;
//list為類(lèi)鏈表
_objc_initializing_classes *list;
Class *classes;
data = _objc_fetch_pthread_data(create);
if (data == nil) return nil;
//鏈表增加類(lèi)節(jié)點(diǎn)
list = data->initializingClasses;
if (list == nil) {
if (!create) {
return nil;
} else {
list = (_objc_initializing_classes *)
_calloc_internal(1, sizeof(_objc_initializing_classes));
data->initializingClasses = list;
}}//將創(chuàng)建的classes接在metaclasses后
classes = list->metaclasses;
if (classes == nil) {
// If _objc_initializing_classes exists, allocate metaclass array,
// even if create == NO.
// Allow 4 simultaneous class inits on this thread before realloc.
list->classesAllocated = 4;
classes = (Class *)
_calloc_internal(list->classesAllocated, sizeof(Class));
list->metaclasses = classes;
}return list;
}
五罢缸、runtime下Class的各項(xiàng)操作(重要幾個(gè))
5.1 add*(增加)
5.1.1 static IMP addMethod(Class cls, SEL name, IMP imp, const char *types, BOOL replace);//增加方法
5.1.2 BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);//增加類(lèi)方法
5.1.3 BOOL class_addIvar(Class cls, const char *name, size_t size,uint8_t alignment, const char *type);//增加實(shí)例變量
5.1.4 static BOOL _class_addProperty(Class cls, const char *name,const objc_property_attribute_t *attrs, unsigned int count,BOOL replace);//增加屬性
5.2 replace*(修改)
5.2.1 IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types); //修改方法
5.2.2 void class_replaceProperty(Class cls, const char *name,const objc_property_attribute_t *attrs, unsigned int n);//修改屬性
5.3 get*(獲取)
5.3.1 static Class getClass(const char *name);//獲取類(lèi)
5.3.2 static ivar_t *getIvar(Class cls, const char *name);//獲取類(lèi)變量(static相當(dāng)于“+“)
5.3.3 Method class_getInstanceMethod(Class cls, SEL sel);//獲取實(shí)例方法
5.3.4 static Method _class_getMethod(Class cls, SEL sel);;//獲取類(lèi)方法
5.3.5 static Protocol *getProtocol(const char *name);//增加協(xié)議
5.4 set*(設(shè)置)
5.4.1 objc_class::setInitialized();//set的initialized初始化
5.4.2 static Class setSuperclass(Class cls, Class newSuper);//設(shè)置父類(lèi)
5.5 其他還有類(lèi)似于 void *objc_destructInstance(id obj);//摧毀實(shí)例對(duì)象等等
六、Class的重要函數(shù)
6.1 get*(獲取)
6.1.1 object_getClass(id obj);
6.1.2 IMP object_getMethodImplementation(id obj, SEL name);//獲得實(shí)例方法實(shí)現(xiàn)
6.1.3 Ivar object_getInstanceVariable(id obj, const char *name, void **value)//獲取實(shí)例屬性
6.2 set*(設(shè)置)
6.2.1 Class object_setClass(id obj, Class cls);
6.2.2 Ivar object_setInstanceVariable(id obj, const char *name, void *value);//設(shè)置實(shí)例屬性
6.2.3 void object_setIvar(id obj, Ivar ivar, id value);//設(shè)置實(shí)例變量
6.3 其他
6.3.1 static void _class_resolveClassMethod(Class cls, SEL sel, id inst);//動(dòng)態(tài)添加類(lèi)方法投队,不必在乎方法是否存在
6.3.2 static void _class_resolveInstanceMethod(Class cls, SEL sel, id inst);//動(dòng)態(tài)添加實(shí)現(xiàn)方法枫疆,不必在乎方法是否存在
6.3.3 unsigned _class_createInstancesFromZone(Class cls, size_t extraBytes, void *zone,id *results, unsigned num_requested);//創(chuàng)建實(shí)例存儲(chǔ)空間
6.4 消息轉(zhuǎn)發(fā)
6.4.1 void? ? instrumentObjcMessageSends(BOOL flag);//flag傳入YES,運(yùn)行時(shí)發(fā)送的所有消息都會(huì)打印到/tmp/msgSend-xxxx文件里了敷鸦。
站在巨人的肩膀上才有這些總結(jié)
菜鳥(niǎo)走向大牛养铸,大家共同前進(jìn),如果覺(jué)得不錯(cuò)轧膘,請(qǐng)給個(gè)贊/關(guān)注。
一起交流學(xué)習(xí)兔甘,有問(wèn)題隨時(shí)歡迎聯(lián)系谎碍,郵箱:383708669@qq.com