这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战
将实例对象isa进行&运算,可得到类对象的地址。同样在OC中,类也是一个对象。既然是对象,也会存在isa指针,指向他所属的类。这就是我们所说的元类(MetalClass)。
- 类也是一个对象,也存在isa指针,指向它所属的类。即:元类(
MetalClass) - 元类初探:实例对象isa -> 类isa -> 元类
- 对象的
isa为nonpoionter类型,除了类对象地址,isa中包含类信息,所以&运算后地址不同 - 类的
isa为非nonpointer类型,属于纯isa指针,只存储类对象的地址,所有&运算后地址相同
1. isa走位&继承链
1.1 isa走位
NSObject作为根类,它的isa指向的元类,称为根元类。- 根元类的地址和
XXClass元类isa指向的地址相同。 XXClass的元类isa,指向的并不是NSObject,而是根元类(NSObject的元类)。- 根元类的
isa指向自己。
- 实例对象isa -> 类isa -> 元类isa -> 根元类isa -> 自己
- 根类的实例对象isa -> 根类isa -> 根元类isa -> 自己
1.2 继承链
继承链流程图
- 继承关系只来自于类,对象之间没有这层关系
- 类和元类都存在继承链
- 元类的父类是父类的元类
- 类的继承链:类->父类->根类->nil
- 元类的继承链:元类->父类的元类->根元类->根类->nil
NSObject作为根类,它才是真正的万物之主,所有类都源于NSObject
1.3 官方流程图
- isa走位:实例对象isa ——>类isa ——>元类isa ——>根元类isa ——>自己
- 类的继承链:类 ——>父类——>根类——>nil
- 元类的继承链:元类——>父类的元类——>根元类——>根类——>nil
2类的结构
2.1源码分析
类也是一个对象,有自己的数据结构,而类的底层来自objc_class结构体,可通过源码分析类的结构,在objc-runtime-new.h中,可以看到objc_class结构体的定义:
struct objc_class : objc_object {
objc_class(const objc_class&) = delete;
objc_class(objc_class&&) = delete;
void operator=(const objc_class&) = delete;
void operator=(objc_class&&) = delete;
// 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
...
};
从上面的源码定义来看,我们的类也是一个对象,只是里面比对象多了几个成员变量superclass、cache、bits。
- superclass :这个就是指向父类的指针。
- cache(cache_t):通过分析cache_t 的结构,我们可以得出cache_t这个占用的内存空间为16字节。所以按照内存平移的规则我们可以知道class_data_bits_t和类首地址之间的差距是32字节(isa:8字节,superclass:8字节,cache:16字节)
- bits(class_data_bits_t)
- superclass为结构体指针,存储父类
- cache为cache_t结构体,存储方法缓存
- bits为class_data_bits_t结构体,存储方法、属性、协议列表等