Objective-C
Objective-C是C語言的超集网梢,我們平時(shí)寫得OC震缭,底層的實(shí)現(xiàn)都是C\C++代碼,OC的對象战虏、類是基于C\C++的結(jié)構(gòu)體實(shí)現(xiàn)的拣宰。
可以使用以下命令行將OC代碼轉(zhuǎn)換為C\C++代碼(只能作為參考不一定百分百準(zhǔn)確)
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc <OC源文件> -o <輸出的.cpp文件>
如果需要鏈接其他框架,使用- framework參數(shù)烦感,比如-framework UIKit
NSObject
一般我們寫的對象都繼承于NSObject巡社,所以弄清楚NSObject相當(dāng)關(guān)鍵
- NSObject底層實(shí)現(xiàn)相關(guān)源碼
struct NSObject_IMPL{
Class *isa
}
//Class是objc_class結(jié)構(gòu)體指針
typedef objc_class *Class
NSObject類里只有Class isa指針,所以obj對象的地址值就是isa指針的地址值手趣。表面上看之只占用了8個(gè)字節(jié)(指針變量8個(gè)字節(jié))晌该,閱讀OC源碼可以看到實(shí)質(zhì)是分配了16個(gè)字節(jié)。
可以使用以下API查看內(nèi)存使用情況
//一個(gè)實(shí)例對象至少需要多少字節(jié)
class_getInstanceSize([NSObject class]);
//一個(gè)實(shí)例對象實(shí)際占用多少字節(jié)
malloc_size((__brige const void *)obj);
一個(gè)繼承NSObject的類的結(jié)構(gòu)體
//例如
@interface Person : NSObject
@property (nonatomic, assign) int age;
@end
struct Person_IMPL{
stuct NSObject_IMPL NSObject_IVARS;
int _age;
}
//NSObject_IMPL的成員變量只有isa指針一個(gè)绿渣,所以實(shí)際結(jié)構(gòu)體等價(jià)如下朝群,person實(shí)例對象的地址值還是isa指針的地址值,再繼承也同理
struct Person_IMPL{
Class *isa;
int _age;
}
OC對象分類
OC對象分為三類:instance對象(實(shí)例對象)中符、class對象(類對象)姜胖、meta-class對象(元類對象)
- instance對象:通過類alloc出來的對象,每次alloc都會(huì)創(chuàng)建新的實(shí)例對象
NSObject *obj1 = [[NSObject alloc] init];
NSObject *obj2 = [[NSObject alloc] init];
//obj1淀散、obj2都是instance對象右莱,它們是不同的兩個(gè)對象蚜锨,分別占據(jù)著不同的內(nèi)存
instance對象在內(nèi)存中存儲(chǔ)的信息有isa指針和其他成員變量。
- class對象(類對象)
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];
Class objectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = object_getClass(object1);
Class objectClass4 = object_getClass(object2);
Class objectClass5 = [NSObject class];
objectClass1 ~ objectClass5都是NSObject的class對象
它們都是同一個(gè)對象隧出,每一個(gè)類在內(nèi)存中有且只有一個(gè)class對象
class對象在內(nèi)存中存儲(chǔ)的信息主要包括:
isa指針
superclass指針
類的屬性信息(@property)踏志、類的對象方法信息(instance method)
類的協(xié)議信息(protocol)、類的成員變量信息(ivar)
- meta-class(元類對象)
//獲取元類對象的方法
Class objMetaClass = object_getClass([NSObject class]);
/*
注意:這個(gè)方法獲取到的還是類對象
Class objMetaClass = [[NSObject class] class];
*/
objectMetaClass是NSObject的meta-class對象(元類對象)
每個(gè)類在內(nèi)存中有且只有一個(gè)meta-class對象
meta-class對象和class對象的內(nèi)存結(jié)構(gòu)是一樣的胀瞪,只是用途不一樣而已针余,在內(nèi)存中存儲(chǔ)的信息主要包括:
isa指針
superClass指針
類的類方法信息
......
- Class的結(jié)構(gòu)
//struct objc_class 結(jié)構(gòu)
struct objc_class{
Class isa;
Class superclass;
Cache_t cache;//方法緩存
class_data_bit_t bit;//用于獲取類的具體信息
}
// bit & FAST_DATA_MASK 得到類的具體信息
struct class_rw_t { // rw表示可讀寫
uint32_t flags;
uint32_t version;
const class_ro_t *ro;
method_array_t methods; //method_t 二維數(shù)組
property_array_t properties; //屬性二維數(shù)組
protocol_array_t protocols; //協(xié)議二維數(shù)組
Class firstSubclass;
Class nextSiblingClass;
char *demangledName;
}
//struct class_ro_t 的結(jié)構(gòu)
struct class_ro_t { //ro表示只讀
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize;
#ifdef __LP64__
uint32_t reserved;
#endif
const uint8_t * ivarLayout;
const char * name; //類名
method_list_t * baseMethodList; //方法列表
protocol_list_t * baseProtocols; //協(xié)議列表
const ivar_list_t * ivars; //成員變量列表
const uint8_t * weakIvarLayout;
property_list_t *baseProperties;
}
isa指針和supclass指針
- instance的isa指針指向class
instance調(diào)用對象方法時(shí),通過isa指針找到class凄诞,找出對應(yīng)的對象方法進(jìn)行調(diào)用 - class的isa指針指向meta-class
調(diào)用類方法時(shí)圆雁,通過class的isa找到meta-class,找出對應(yīng)的類方法進(jìn)行調(diào)用
從Arm64開始帆谍,優(yōu)化了isa指針伪朽,isa & ISA_MASK才是真正的地址值
- class對象的superclass指針指向父類class對象
當(dāng)instance調(diào)用父類對象方法時(shí),先通過isa指針找到class汛蝙,再通過class對象的superclass指針找到父類烈涮,然后再找出對應(yīng)對象方法進(jìn)行調(diào)用 -
meta-class對象的superclass指針指向父類的meta-class對象
調(diào)用父類類方法時(shí),通過class的isa找到meta-class窖剑,再通過meta-class對象的superclass指針找到父類坚洽,然后再找出對應(yīng)的類方法進(jìn)行調(diào)用
isa、superclass總結(jié)