OC对象解析

一、OC对象分为三类

1、实例对象 :instance对象

2、类对象: class对象

3、元类对象 :meta-class对象

二、OC对象内存分配

1、实例对象:alloc出来的对象,分布在堆区。

2、类对象:系统编译加载进内存时自动创建的,在内存中只存在一份,分布在数据区。

3、元类对象:系统编译加载进内存时自动创建的,在内存中只存在一份,分布在数据区。

从下面图打印的地址可以看出,类对象及元类对象的地址与age全局变量地址相近说明都是存在数据区。实例对象地址相比数据段地址更大,栈地址是最大部分的地址,与内存的区域分配原则相同。可确定实例对象内存是属于堆区,栈变量内存地址是栈区(高地址)。

内存分配地址

总结:每个类有且只有一个类对象、元类对象,存储在数据区。

三、struct objc_class的结构

1、类对象的结构(非objc2情况下)在目前的objc2后是不可用的,过时的。

从objc源码中查找https://opensource.apple.com/tarballs/objc4/

在目前的objc2.0的最新源码中,struce objc_class结构如下:

总结下struct objc_class的结构简化表示如下:

注意:Class是struct objc_class结构指针,

总结Class里面成员包括如下:

class对象在内存中存储的信息主要包括: isa指针、superClass指针、类的属性信息(properties)、类的对象实例方法列表(methods)、协议列表(protocols)、成员变量列表(ivars)、方法缓存列表(cache)。

获取类对象的方法如下:


注意点:Class objClass = [[NSObject class]class];这样得到的都是类对象,不是元类对象。

2、元类meta-class的结构与类对象class的结构是一样的。(每个类都存在唯一的一个元类对象meta-class)

元类对象meta-class的用途,内存存储的主要信息:存储着类方法列表,缓存列表,isa,superClass等信息。

获取元类API: Class metaclass = object_getClass([NSObject class]);



四、isa指针与superclass总结


1、instance的isa指向class。

2、class的isa指向meta-class。

3、meta-class的isa指向基类的meta-class。

4、class的superclass指向父类的class,如果没有父类,superclass指针为nil。

5、meta-class的superclass指向父类的meta-class,基类的meta-class的superclass指向基类的class(特殊点)。

6、instance调用对象方法的轨迹:isa找到class,先从缓存列表找然后去方法列表找,如果方法不存在,就通过superclass找父类。

7、class调用类方法的轨迹:isa找meta-class,先从缓存列表找然后去方法列表找,如果方法不存在,就通过superclass找父类。


isa指针指向

四、isa指针的真实地址

1、实例对象的isa指针是指向类对象的地址值。类对象的isa指针指向的是元类对象的地址值。但是是否是这样呢?请看截图:


从打印的结果可以看出,person对象实例的isa的值:0x001d800100002531 与person的类对象的地址值:0x0000000100002530是不同的。然而isa&0x00007ffffffffff8位运算后,可以得到person类对象的地址值。

原因:在arm64之前,isa的值就是类对象or元类对象的地址值,但是在arm64架构之后,程序设计有所改变,isa的值需要进行一次位运算(需要&ISA_MASK一个掩码)后,才能够得到isa的真实地址值。


注意:可以在https://opensource.apple.com/tarballs/objc4/源码里面找到ISA_MASK.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容