当前位置:   article > 正文

iOS runtime 机制解读(结合 objc4 源码)_objc4 包含哪些功能

objc4 包含哪些功能

欢迎访问我的博客原文

Runtime 是指将数据类型的确定由编译时推迟到了运行时。它是一套底层的纯 C 语言 API,我们平时编写的 Objective-C 代码,最终都会转换成 runtime 的 C 语言代码。

不过,runtime API 的实现是用 C++ 开发的(源码中的实现文件都是 .mm 文件)。

为了更全面地理解 runtime 机制,我们结合最新的objc4 源码来进行解读。

消息传递

我们知道 Objective-C 是面向对象开发的,而 C 语言则是面向过程开发,这就需要将面向对象的类转变成面向过程的结构体

在 Objective-C 中,所有的消息传递中的“消息”都会被编译器转化为:

id objc_msgSend ( id self, SEL op, ... );

比如执行一个对象的方法:[obj foo];,底层运行时会被编译器转化为:objc_msgSend(obj, @selector(foo));

那么方法内部的执行流程究竟是怎么样的呢?我先来了解一些概念。

概念

objc_object

Objective-C 对象是由 id 类型表示的,它本质上是一个指向 objc_object 结构体的指针。

typedef struct objc_object *id;

union isa_t {
   
    isa_t() {
    }
    isa_t(uintptr_t value) : bits(value) {
    }

    Class cls;
    uintptr_t bits;
#if defined(ISA_BITFIELD)
    struct {
   
        ISA_BITFIELD;  // defined in isa.h
    };
#endif
};

struct objc_object {
   
private:
    isa_t isa;
// public & private method...
}

我们看到 objc_object 的结构体中只有一个对象,就是指向其类的 isa 指针。

当向一个对象发送消息时,runtime 会根据实例对象的 isa 指针找到其所属的类。

objc_class

Objective-C 的类是由 Class 类型来表示的,它实际上是一个指向 objc_class 结构体的指针。

typedef struct objc_class *Class;

objc_class 结构体中定义了很多变量:

struct objc_class : objc_object {
   
    // 指向类的指针(位于 objc_object)
    // Class ISA;
    // 指向父类的指针
    Class superclass;
    // 用于缓存指针和 vtable,加速方法的调用
    cache_t cache;             // formerly cache pointer and vtable
    // 存储类的方法、属性、遵循的协议等信息的地方
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    // class_data_bits_t 结构体的方法,用于返回class_rw_t 指针()
    class_rw_t *data() {
    
        return bits.data();
    }
    // other methods...
}

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;
    
    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;
    
    Class firstSubclass;
    Class nextSiblingClass;
    
    char *demangledName;

#if SUPPORT_INDEXED_ISA
    uint32_t index;
#endif
    // other methods
}

objc_class 继承自 objc_object,因此它也拥有了 isa 指针。除此之外,它的结构体中还保存了指向父类的指针、缓存、实例变量列表、方法列表、遵守的协议等。

元类

元类(metaclass)是类对象的类,它的结构体和 objc_class 是一样的。

由于所有的类自身也是一个对象,我们可以向这个对象发送消息,比如调用类方法。那么为了调用类方法,这个类的 isa 指针必须指向一个包含类方法的一个 objc_class 结构体。而类对象中只存储了实例方法,却没有类方法,这就引出了元类的概念,元类中保存了创建类对象以及类方法所需的所有信息。

为了更方便理解,举个例子:

- (void)eat;    // 一个实例方法
+ (void)sleep;  // 一个类方法

// 那么实例方法需要由类对象来调用:
[person eat];
// 而类方法需要由元类来调用:
[Person sleep];

假如 person 对象也能调用 sleep 方法,那我们就无法区分它调用的就究竟是 + (void)sleep; 还是 - (void)sleep;

类对象是元类的实例,类对象的 isa 指针指向了元类。

这个说法可能有点绕,借助这张经典的图来理解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rJIMqnfn-15

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/1022485
推荐阅读
相关标签
  

闽ICP备14008679号