通过之前对象的分析, 知道每一个
OC对象里有一个isa的属性。通过isa与ISA_MASK的位与,得到一个指针地址,那这个地址是什么,它又有什么信息。这是本篇要探索的内容。
先贴上经典的isa流程图 ,本章将围绕这张图来阐述内容。
0x00 -- 对象的isa分析
-
通过
LLDB打印输出,对象内存的这个首地址0x001d80010003b59存储的是属性isa。 -
通过对
isa属性与ISA_MASK的值按位与,得出shiftcls的地址,通过对地址打印,这个值是类对象的地址。 -
进一步反向证明,打印
OtherObj.class的内存布局,类的首地址与对象的isa一毛一样。所以通过对象的isa可以找到它所属的类。
0x01 -- 类对象的isa的分析
struct objc_class : objc_object {
// Class ISA; // 8
Class superclass; // 8
cache_t cache; // 16 // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags 属性 方法 协议
.....
}
进一步探索类对象的内存布局, 0x0000000100003b30类的首地址isa,第二个是父类superclass
- 通过类对象的
isa的打印,输出依然是OtherObj,这个是OtherObj的元类 - 接着对
元类的isa打印输出,是NSObject,这个类是NSObject类吗?
通过调试,明显不是同一个NSObject类,那它是什么呢?
打印了NSObject类的元类,发现根类的地址和OtherObj元类的isa地址是一样的,叫根元类。
0x02 -- 总结isa走位
对象的isa指向它的类,
类的isa指向它的元类.
所有类的元类指向根元类.,
根元类指向自己,形成闭环,这里的根元类就是NSObject。
0x03 -- superclass与metaclass继承关系
类(subclass)继承自它的父类(superclass)
父类最终会继承自根类(rootclass)
类的元类也有父类的继承关系, 一直继承到根元类(rootclass),根元类继承nil。
Objective-C中的对象可以说是万物起源于NSObject.
子类的元类(metaclass)继承自父类的元类(meta superclass)
父类的元类最终会继承自根元类(root metaclass)。
根元类(root metaclass)会继承自NSObject
通过以上的分析,万物皆是由NSObject创建,即万物皆对象.
验证class在内存中存在的个数。
Class cls1 = [Demo class];
Class cls2 = [Demo alloc].class;
Class cls3 = object_getClass([Demo alloc]);
通过以上获取类对象的地址,这些地址都是相同的, 说明类在系统中只存在一份。
面试题
objc_class与objc_object的关系?
- 结构体
objc_class是继承自objc_object结构体,objc_object有一个isa属性,通过继承使objc_class也有了这个属性。 - 在
oc中定义一个对象,该对象满足objc_object特性, 也就是有isa属性。 NSObject是以objc_class为模版创建的,objc_class继承自objc_object,所以有isa属性。所以继承自NSObject的类也都继承了isa的这个属性。- 所以
对象都有isa的属性, 表示当前isa的关系。 指向谁,属于谁。
objc_object与对象的关系?
对象都是以objc_object为模版继承创建的。- 在
OC层面上所有对象来自NSObject,但是真正到底层以c/c++语言的objc_object的结构体。 objc_object与对象的关系是继承的关系。
总结
在结构层面可以通俗的理解为上层OC与底层的对接:
- 下层通过
结构体定义的模版,例如objc_class,objc_object - 上层是通过底层的
模版的一些类型来创建, 如Person、 - 从以上所学可以看出在
oc中万物皆对象