浅谈系列-class 、meta-class结构简单理解

917 阅读3分钟

浅谈系列-OC对象创建出来到底是怎么样的呢

导语:通过浅谈系列的第一篇,了解OC对象,类,元类的一些基本情况,今天我们开始了解一下类对象,元类对象的结构。下一个阶段探讨OC的消息机制,了解了类和元类的结构有助于快速理解消息机制在发送消息阶段是如何查找方法的。

isa指针

  • 从64bit开始,isa并不是直接储存指针,而是储存了非常多信息。

要获得isa里存class,meta-class地址的指针,需要进行一下位运算才行 isa & ISA_MASK

本篇重点是探讨类和元类的结构,关于isa就不多说了。

class 、meta-class

  • class、meta-class的结构是struct objc_class

类对象,元类对象本质就是结构体,并且类和元类的结构都是一样的。只是存储的信息不一样。

struct objc_class {
    Class isa;
    Class superclass;
    cache_t cache;           
    class_data_bits_t bits;    
};

struct objc_class说明
isa类的isa指向元类对象(元类的isa直接指向基类的元类对象)
superclass类的superclass就指向父类,元类的superclass指向父类的元类
cache方法缓存(方法调用会先在此处查找)
bits& FAST_DATA_MASK 与运算,可以找到class_rw_t结构体
  • class_rw_t:通过查看源码,class_rw_t简化之后得出以下内容:
struct class_rw_t{
    ...
    const class_ro_t *ro;
    const method_array_t methods;
    const property_array_t properties;
    const protocol_array_t protocols;
    ...

}
struct class_rw_t说明
roro结构体重包含了一些类的信息(instance对象占用的内存,类名,成员列表)
methods方法列表
properties属性列表
protocols协议列表
  • struct class_ro_t:通过查看源码,class_ro_t简化之后得出以下内容:
struct class_ro_t{
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif

    union {
        const uint8_t * ivarLayout;
        Class nonMetaclass;
    };
    
    char * name;
    void *baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars;
    
    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;
}
struct class_ro_t说明
instanceSizeinstance对象所占用的内存
name类名
baseMethodList基本方法列表
baseProtocols基本协议列表
ivars成员列表
baseProperties基本属性列表

class_rw_tclass_ro_t 都有方法列表,协议列表,属性列表。那么有什么不同呢?

简单来说,class_ro_t是只读内存区,里面的所有数据初始化之后都是不可更改的,方法列表,协议列表,属性列表,成员变量列表都是类的最原始并且不可更改的数据。

class_rw_t是可读写内存区,后期加入的可更改的数据都在此处,分类(category)中扩展的数据会在runtime运行期加入到class_rw_t

总结:

  • objc_class结构体的bits & FAST_DATA_MASK可以获取class_rw_tclass_ro_t又是class_rw_t里的一个成员。

  • 对象的成员变量,对象方法,协议,属性这些数据都保存到类对象里面,类方法在元类对象里。 (如果有一定c,c++基础,可以仿照苹果官方的代码,写出一个objc_class结构体进行调试)

浅谈系列-OC方法调用到底是个什么流程

浅谈系列 - KVO&KVC到底是怎么样实现的

浅谈系列-分类的结构和加载时机

浅谈系列-load 和 initialize的调用时机和实际运用

浅谈系列-block如何工作的