iOS开发 OC对象原理--对象的本质

452 阅读3分钟

Clang如何将目标文件编译成c++文件

image.png

示例

image.png

对象是什么?

对象在底层的本质是结构体

NSObject的底层是objc_object,所以id的底层是objc_object *;

Class的底层是objc_class *

set和get方法的底层:

image.png

位域是什么?

  1. 我们先看一个结构体,根据结构体内存对齐可知该结构体所占内存为4个字节,但其实我们完全可以只用1位来存储1个布尔值。 image.png

  2. 所以我们便可以使用位域,图中的1代表1位,这样整个结构体只占1个字节,为什么是1个字节呢?因为没有半个字节,该结构体的内存大概示意为0000 1111,这样我们便可以大大节省内存空间。

image.png

联合体是什么?

联合体的结构如图所示,联合体中的成员变量是互斥的,比如当给name赋值时,age和height便没有数据或里面是脏数据,在特殊的场合下使用可以大大节省内存空间。 image.png

结构体和联合体的优缺点

image.png

结合联合体和位域使用

可以节省内存空间,但通常不建议使用,使用的时间成本大,建议只在特殊情况使用。 image.png

initIsa作用

将当前堆内存申请的结构体指针和class绑定在一起。

Isa底层结构

1. 初始化Isa

image.png

2. initIsa内部

image.png

image.png

3. 从上面可看出isa是通过isa_t初始化得来的,isa_t内部是联合体及结构体组合使用,如下图所示

image.png

4. 所以isa的实际内部结构在ISA_BITFIELD里面,如下图所示

image.png

5. 从上图可知,isa内部主要存储了以下内容:

  • nonpointer: 表示是否对isa指针开启指针优化,0表示纯isa指针,1表示不只是类对象地址,isa中包含了类信息、对象的引用计数等。
  • has_assoc: 关联对象标志位,0没有,1存在。
  • has_cxx_dtor: 该对象是否有c++或者Objc的析构器,如果有析构函数,则需要做析构逻辑,如果没有,则可以更快的释放对象。
  • shiftcls: 存储类指针的值;开启指针优化的情况下,在arm64架构中有33位用存储类指针。
  • magic: 用于调试器判断当前对象是真的对象还是没有初始化的空间。
  • weakly_referenced: 标志对象是否被指向或者曾经指向一个ARC的弱变量,没有弱引用的对象可以更快释放。
  • deallocation: 标志对象是否正在释放内存。
  • has_sidetable_rc: 当对象引用计数大于10时,则需要借用该变量存储进位。
  • extra_rc: 当表示该对象的引用计数值,实际上是引用计数值减1,例如,如果对象的引用计数为10,那么extra_rc为9。如果引用计数大于10,则需要使用到下面的has_sidetable_rc。

通过isa反推出class

将isa地址和掩码做位运算

掩码 image.png

isa地址

image.png

做位运算

image.png

通过Isa联合体的信息做位运算

image.png 由上图可知,shiftcls存储的是类地址,所以只需要将isa地址左移3位,再右移20位,再左移17位,即可得到class地址,如下图所示

image.png

Init的意义

init方法内部实际并没有做什么事,作用在于提供接口,便于扩展 init 提供接口 便于扩展

New的意义

new方法其实就等于alloc + init