问题: 简述iOS的 struct objc_class 的结构.

问题: 简述iOS的 Class对象 的底层结构.


注: 本问题回答基于 objc4-818.2 版本

  1. objc_class结构体继承于objc_object结构体,objc_object结构体有且只有一个isa指针.

  2. objc_class 含有一个 Class类型的 superclass成员变量.

  3. objc_class 含有一个 cache_t类型的 cache成员变量,主要作用是方法缓存.

  4. objc_class 含有一个 class_data_bits_t类型的 bits.

struct objc_object {
    Class isa;
};

struct objc_class: objc_object {
    Class superclass;
    cache_t cache;
    class_data_bits_t bits;

    ...

};

通过 class_data_bits_t 的 data() 函数可以获得class_rw_t的结构体,函数内部主要与FAST_DATA_MASK宏进行了一次与运算.如下所示.

#define FAST_DATA_MASK 0x00007ffffffffff8UL

struct class_data_bits_t {

    uintprt_t bits;

    ...

public:

    class_rw_t* data() const {
        return (class_rw_t *)(bits & FAST_DATA_MASK);
    }

    ...

};

在 读写的列表 class_rw_t 结构体中主要含有一下内容.

注:在最新的objc818.2的代码结构,已经把相关成员变量实现已经直接修改为函数.相关成员变量已经存在了 class_rw_ext_t的结构体中了.

  1. 返回值为只读的 class_ro_t 类型的 ro() 函数.

  2. 返回值为 method_array_tmethod() 函数.

  3. 返回值为 property_array_tproperties() 函数.

  4. 返回值为 protocol_array_tprotocols() 函数.

struct class_rw_ext_t {
    DECLARE_AUTHED_PTR_TEMPLATE(class_ro_t)
    class_ro_t_authed_ptr<const class_ro_t> ro;
    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;
    char *demangledName;
    uint32_t version;
};

struct class_rw_t {
    uint32_t flags;

    ...

private:
    using ro_or_rw_ext_t = objc::PointerUnion<const class_ro_t, class_rw_ext_t, PTRAUTH_STR("class_ro_t"), PTRAUTH_STR("class_rw_ext_t")>;

    const ro_or_rw_ext_t get_ro_or_rwe() const {
        return ro_or_rw_ext_t{ro_or_rw_ext};
    }

public:
    const class_ro_t* ro() const {
        auto v = get_ro_or_rwe();
        if (slowpath(v.is<class_rw_ext_t *>())) {
            return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->ro;
        }
        return v.get<const class_ro_t *>(&ro_or_rw_ext);
    }

    const method_array_t method() const {
        auto v = get_ro_or_rwe();
        if(v.is<class_rw_ext_t *>()) {
            return v.get<const class_rw_ext_t *>(&ro_or_rw_ext)->method;
        } else {
            return method_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext_t)->baseMethods()};
        }
    }

    const property_array_t properties() const {
        auto v = get_ro_or_rw_rwe();
        if(v.is<class_rw_ext_t *>()) {
            return v.get<const class_rw_ext_t *>(&ro_or_rw_ext)->properties;
        } else {
            return method_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext_t)->baseProperties};
        }
    }

    const protocol_array_t protocols() const {
        auto v = get_ro_or_rw_rwe();
         if(v.is<class_rw_ext_t *>()) {
            return v.get<const class_rw_ext_t *>(&ro_or_rw_ext)->protocols;
        } else {
            return method_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext_t)->baseProtocols};
        }       
    }
};

相比于 struct class_rw_t , struct class_ro_t 主要存储的是以下内容.

  1. 成员变量的大小信息 - instanceSize.

  2. 类名 - name.

  3. 方法列表 baseMethodList.

  4. 协议列表 baseProtocols.

  5. 成员变量列表 ivars.

  6. 属性列表信息 basePropreties.

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif

    explicit_atomic<const char *> name; // 类名

    void *baseMethodList;
    protocol_array_t *baseProtocols;
    const ivar_list_t *ivars;
    property_array_t *baseProperties;
}

IT界无底坑洞栋主 欢迎加Q骚扰:676758285