通过之前对象的分析, 知道每一个
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
中万物皆对象