美文网首页
iOS进阶之Class的底层原理

iOS进阶之Class的底层原理

作者: 枫叶无处漂泊 | 来源:发表于2020-10-27 11:53 被阅读0次

一、Class的定义

我们知道不管是类对象还是元类对象,类型都是Class,class和mete-class的底层都是objc_class结构体的指针,内存中就是结构体。

Class objectClass = [NSObject class];        
Class objectMetaClass = object_getClass([NSObject class]);

点击Class看一下Class定义,我们发现:

typedef struct objc_class *Class;

Class对象其实是一个指向objc_class结构体的指针,因此我们可以说类对象或元类对象内部结构是一个objc_class结构体。

我们来到objc_class内部,可以看到这段在底层原理中经常出现的代码:

struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class _Nullable super_class                              OBJC2_UNAVAILABLE;
    const char * _Nonnull name                               OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
    struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */

这部分代码相信在文章中很常见,但是OBJC2_UNAVAILABLE;说明这些代码已经不在使用了。
那么目前objc_class的结构是什么样的呢?我们通过objc源码中去查找objc_class结构体的内容。

二、objc_class现在的内部结构

struct objc_class : objc_object {
    //Class ISA
    Class superclass;
    cache_t cache;
    class_data_bits_t bits;
    class_rw_t *data() {
        return bits.data();
    }
    void setData(class_rw_t *newData) {
        bits.setData(newData);
    }
}

通过上面的内部结构体表明:objc_class 继承 objc_object,看一下class_object内部结构:

struct class_object {
    private:
        isa_t isa;
    
    public:
        Class ISA();
        
        Class getIsa();
}

我们发现objc_object中有一个isa指针,那么objc_class继承objc_object,也就同样拥有一个isa指针.

class_rw_t是通过bits调用data方法得来的,我们来到data方法内部实现.代码如下:

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

我们可以看到,data函数内部仅仅对bits进行&FAST_DATA_MASK操作.

三、class_rw_t内部结构

查看一下class_rw_t内部结构:

// 可读可写
struct class_rw_t {
    // Be warned that Symbolication knows the layout of this structure.
    uint32_t flags;
    uint32_t version;
    const class_ro_t *ro;
     /*
     这三个都是二位数组,是可读可写的,包含了类的初始内容、分类的内容。
     methods中,存储 method_list_t ----> method_t
     二维数组,method_list_t --> method_t
     这三个二位数组中的数据有一部分是从class_ro_t中合并过来的。
     */
    method_list_t methods; // 方法列表(类对象存放对象方法,元类对象存放类方法)
    property_list_t properties; // 属性列表
    protocol_lsit_t protocols; //协议列表

    Class firstSubclass;
    Class nextSiblingClass;
    
    //...
}
  • class_rw_t :rw代表可读可写的类
  • class_ro_t :指向只读的结构体,存放类初始信息
  • method_lst_t、property_list_t、protocol_lsit_t这三个都是可读可写的二维数组。二维数组例如:method_list_t -->(sublist) method_list_t --> method_t,这三个二维数组中的数据有一部分是从class_ro_t中合并过来的。

四、class_ro_t内部结构

看一下class_ro_t内部代码如下:

struct class_ro_t {  
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
    uint32_t reserved;

    const uint8_t * ivarLayout; //处理strong引用

    const char * name;
    method_list_t * baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars;

    const uint8_t * weakIvarLayout; //处理weak引用
    property_list_t *baseProperties;
};

class_ro_t存储了当前类在编译期就已经确定的属性、方法以及遵循的协议。

baseMethodList,baseProtocols,ivars,baseProperties三个都是一位数组。

总结

ogjc_class的整体内部结构如下:

objc_class内部结构.png

相关文章

网友评论

      本文标题:iOS进阶之Class的底层原理

      本文链接:https://www.haomeiwen.com/subject/ilztvktx.html