OC底层04:类的结构
2020-09-14 本文已影响0人
ZAREMYDREAM
之前分析isa指针,今天具体来分析下类的结构。
元类
先创建一个Person类,然后实例化一个对象,然后用LLDB进行分析
@interface Person : NSObject
@end
@implementation Person
@end
//main中
NSObject *obj = [NSObject alloc];
Person *objc1 = [Person alloc];
-
先来看objc1的isa,上篇已经讲了第一个为isa指针,以及如何获取其绑定的类。objc1对象的isa指针指向Person类
- 当我们读取isa指向的这个Person类的内存信息时,会发现他也有个isa,并且指向不同的地址
0x0000000100002170
。
-
继续查看,会发现isa任然指向Person
-
很明显,这两个Person的地址时不同,这个第二个Person便是元类。
-
继续查看这个Person(元类)的isa,我们会发现他指向NSObject(元类)
-
为什么说他是元类而不是NSObject呢,因为它与NSObject不同。
-
NSObject(元类)的isa指向了它自己,并不会往上指,所以它是根,我们叫根元类
-
所以我们最后能找到这样的关系。
isa流程图.png
总结:
-
对象
的isa
指向对象的对应的类
-
类
的isa
指向对应的元类
-
元类
的isa
指向根元类
-
根元类
的isa
指向自己
objc_class & objc_object
要了解类的结构,就要从起源NSObject
开始,查看源码可以发现,NSObject类中有一个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
是一个结构体指针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
主要封装一个对象
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
- 大部分对象都是继承
objc_object
来的,根据objc_class
的结构,可以通过地址偏移
来查找相关类信息。
对于一个objec_class
,根据内存计算方法
-
isa
8个字节 -
superclass
8个字节 -
cache
16个字节 - 要获取
bits
需要偏移32个字节
5.objc_class
中提供了一个获取类信息的方法class_rw_t *data() const
- 阅读
class_rw_t
,我们会发现他提供了各种类信息相关的方法
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
类添加相应的信息
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
- (void)run;
@end
@implementation Person
- (void)run {
};
@end
-
Person
类信息获取