class的本质

在OC中,类对象(class对象)和元类对象(meta-class对象)的本质结构都是struct objc_class指针,即在内存中就是结构体。

Class clas = [NSObject class];   

来到class底层源码,我们可以看到:

typedef struct objc_class *Class;

class对象其实是一个objc_class结构体的指针。因此我们可以说类对象或元类对象在内存中其实就是objc_class结构体。

相信很多人在查看源码或者看一些底层博客的时候,经常会看到下面一段代码,来讲述class的内部结构:

typedef struct objc_class *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;

这段源码其实讲述的也是class内部结构,包含成员变量列表方法列表方法缓存以及协议列表。细心的人可能会发现,这段代码里面是有if判断条件的:

#if !__OBJC2__

在结尾处也有:

OBJC2_UNAVAILABLE

判断条件是非OC2.0版本,也就是说在OC2.0之前的版本中,class底层的结构体中包含上面代码所讲述的,但我们现在所用的最新版肯定是OC2.0版本了,所以这段代码就不再使用了。

那么新的class底层源码是什么样子呢?我们截取objc源码中objc_class结构体部分内容:

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags

    class_rw_t *data() { 
        return bits.data();
    }

我们发现objc_class结构体继承 objc_object并且结构体内有一些函数,因为这是c++结构体,在c上做了扩展,因此结构体中可以包含函数。注意观察注释掉的Class ISA这一行代码:

    // Class ISA;

我们来到objc_object内,继续截取部分代码:

struct objc_object {
private:
    isa_t isa;

public:

    // ISA() assumes this is NOT a tagged pointer object
    Class ISA();

    // getIsa() allows this to be a tagged pointer object
    Class getIsa();

我们发现objc_object中有一个isa指针,那么objc_class继承objc_object,也就同样拥有一个isa指针。继承来了isa指针,所以上文我们提到了Class ISA也就被注释掉了。

看完源码,那么我们来分析一下class底层的objc_class结构体:

objc_class结构体

可以看到结构体中只包含isasuperclasscachebits。而在上文的源码中有这样一个方法:

    class_rw_t *data() { 
        return bits.data();

也就是说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.jpeg

rw代表readwrite,可读可写
t代表table,列表

struct class_rw_t结构体中就包含了方法列表、属性列表以及协议列表,这些都是可读可写的。其中还包含一个struct class_ro_t的结构体:

class_ro_t.jpeg

ro代表readonly,只读

struct class_ro_t的结构体中包含了instance对象占用的内存空间、类名以及成员变量列表,当然这些都是只读的。

最后我们用一张图来总结一下struct objc_class的结构:

struct objc_class内部结构.png

posted @ 2021-12-28 16:31  任淏  阅读(102)  评论(0编辑  收藏  举报