之前分析isa指針,今天具體來分析下類的結(jié)構(gòu)。
元類
先創(chuàng)建一個(gè)Person類,然后實(shí)例化一個(gè)對(duì)象,然后用LLDB進(jìn)行分析
@interface Person : NSObject
@end
@implementation Person
@end
//main中
NSObject *obj = [NSObject alloc];
Person *objc1 = [Person alloc];
-
先來看objc1的isa,上篇已經(jīng)講了第一個(gè)為isa指針,以及如何獲取其綁定的類呵晨。objc1對(duì)象的isa指針指向Person類
- 當(dāng)我們讀取isa指向的這個(gè)Person類的內(nèi)存信息時(shí),會(huì)發(fā)現(xiàn)他也有個(gè)isa,并且指向不同的地址
0x0000000100002170
。
-
繼續(xù)查看,會(huì)發(fā)現(xiàn)isa任然指向Person
-
很明顯,這兩個(gè)Person的地址時(shí)不同,這個(gè)第二個(gè)Person便是元類鲜侥。
-
繼續(xù)查看這個(gè)Person(元類)的isa,我們會(huì)發(fā)現(xiàn)他指向NSObject(元類)
-
為什么說他是元類而不是NSObject呢,因?yàn)樗cNSObject不同褂始。
-
NSObject(元類)的isa指向了它自己,并不會(huì)往上指,所以它是根,我們叫根元類
-
所以我們最后能找到這樣的關(guān)系诸典。
總結(jié):
-
對(duì)象
的isa
指向?qū)ο蟮膶?duì)應(yīng)的類
-
類
的isa
指向?qū)?yīng)的元類
-
元類
的isa
指向根元類
-
根元類
的isa
指向自己
objc_class & objc_object
要了解類的結(jié)構(gòu),就要從起源NSObject
開始,查看源碼可以發(fā)現(xiàn),NSObject類中有一個(gè)Class isa OBJC_ISA_AVAILABILITY
@interface NSObject <NSObject> {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
Class isa OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}
Class
是一個(gè)結(jié)構(gòu)體指針typedef struct objc_class *Class;
而objc_class
繼承自objc_object
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
class_rw_t *data() const {
return bits.data();
}
void setData(class_rw_t *newData) {
bits.setData(newData);
}
……
}
而objc_object
主要封裝一個(gè)對(duì)象
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
- 大部分對(duì)象都是繼承
objc_object
來的,根據(jù)objc_class
的結(jié)構(gòu),可以通過地址偏移
來查找相關(guān)類信息。
對(duì)于一個(gè)objec_class
,根據(jù)內(nèi)存計(jì)算方法
-
isa
8個(gè)字節(jié) -
superclass
8個(gè)字節(jié) -
cache
16個(gè)字節(jié) - 要獲取
bits
需要偏移32個(gè)字節(jié)
5.objc_class
中提供了一個(gè)獲取類信息的方法class_rw_t *data() const
- 閱讀
class_rw_t
,我們會(huì)發(fā)現(xiàn)他提供了各種類信息相關(guān)的方法
const method_array_t methods() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>()->methods;
} else {
return method_array_t{v.get<const class_ro_t *>()->baseMethods()};
}
}
const property_array_t properties() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>()->properties;
} else {
return property_array_t{v.get<const class_ro_t *>()->baseProperties};
}
}
const protocol_array_t protocols() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>()->protocols;
} else {
return protocol_array_t{v.get<const class_ro_t *>()->baseProtocols};
}
}
- 我們給
Person
類添加相應(yīng)的信息
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
- (void)run;
@end
@implementation Person
- (void)run {
};
@end
-
Person
類信息獲取