返回

iOS OC类底层bits分析(上)

IOS

iOS OC 类底层 bits 分析(上)

OC 类对象结构简介

在探讨 OC 类的内部结构之前,我们需要先了解一下 OC 类对象的结构。OC 类对象是一个包含有关类本身信息的数据结构,类似于 C++ 中的类模板。类对象的布局因平台和架构的不同而有所差异。

在 iOS 上,类对象通常具有以下结构:

struct objc_class {
    Class isa; // 指向自身类型的指针
    const char *name; // 类名
    long version; // 类版本号
    long info; // 类信息
    long instance_size; // 实例大小
    long ivar_layout; // 实例变量布局
    long weak_ivar_layout; // 弱引用实例变量布局
    const char **method_names; // 方法名列表
    const void **method_imp; // 方法实现列表
    const char **properties; // 属性列表
    const char **ivars; // 实例变量列表
    const int *ivar_offsets; // 实例变量偏移量列表
    const int *weak_ivar_offsets; // 弱引用实例变量偏移量列表
    void *protocols; // 遵循的协议列表
    void *superclass; // 父类
    void *cache; // 缓存数据
    void *vtable; // 虚函数表
};

类对象布局详解

类名和版本:

  • name 字段存储着类名,是一个 C 风格字符串。
  • version 字段存储着类的版本号,用于区分不同版本的类。

实例大小:

  • instance_size 字段存储着该类实例的大小,单位为字节。

方法列表和属性列表:

  • method_namesmethod_imp 字段分别存储着该类的所有方法名和方法实现。
  • properties 字段存储着该类的所有属性。

实例变量布局:

  • ivar_layout 字段存储着该类的所有实例变量的布局信息。
  • ivar_offsets 字段存储着每个实例变量的偏移量,单位为字节。

弱引用实例变量布局:

  • weak_ivar_layout 字段存储着该类的所有弱引用实例变量的布局信息。
  • weak_ivar_offsets 字段存储着每个弱引用实例变量的偏移量,单位为字节。

协议和父类:

  • protocols 字段存储着该类遵循的所有协议。
  • superclass 字段存储着该类的父类。

缓存和虚函数表:

  • cache 字段存储着该类的缓存数据,用于优化方法调用。
  • vtable 字段存储着该类的虚函数表,用于动态绑定。

isa 指针

isa 指针是一个指向类对象的指针,存储在每个 OC 对象的第一个成员变量中。通过 isa 指针,我们可以获取有关该对象所属类的所有信息。

我们可以使用 LLDB 命令 p $object->isa 来查看一个 OC 对象的 isa 指针指向的类对象。

小结

通过了解 OC 类对象的结构,我们可以更好地理解 OC 类的底层实现机制。在下一篇文章中,我们将继续深入探讨 OC 类的 bits 分析,重点关注实例变量和方法实现的存储结构。

常见问题解答

  1. OC 类对象的结构在不同的平台和架构上是否相同?

    • 不完全相同,不同的平台和架构可能略有差异。
  2. 类名是如何存储在类对象中的?

    • 以 C 风格字符串的形式存储在 name 字段中。
  3. 实例变量是如何布局的?

    • 实例变量按照声明顺序连续存储,偏移量存储在 ivar_offsets 字段中。
  4. 弱引用实例变量与普通实例变量有什么区别?

    • 弱引用实例变量不会使对象保持活动状态,而普通实例变量会。
  5. isa 指针指向什么?

    • isa 指针指向该对象所属类的类对象。