iOS——runtime

什么是runtime

我们都知道,将源代码转换为可执行的程序,通常要经过三个步骤:编译、链接、运行
C 语言 作为一门静态类语言,在编译阶段就已经确定了所有变量的数据类型,同时也确定好了要调用的函数,以及函数的实现。
而 Objective-C 语言 是一门动态语言。在编译阶段并不知道变量的具体数据类型,也不知道所真正调用的哪个函数。只有在运行时间才检查变量的数据类型,同时在运行时才会根据函数名查找要调用的具体函数。
而实现 Objective-C 语言 运行时机制的一切基础就是 Runtime。
Runtime 实际上是一个库,这个库使我们可以在程序运行时动态的创建对象、检查对象,修改类和对象的方法。

runtime中的概念解析

runtime中的消息发送机制在“消息传递与消息转发”博客中详细讲解过,因此这里直接贴博客链接,不多赘述:iOS——消息传递和消息转发
在这里插入图片描述

Class(类)

在runtime中,类被定义为指向objc_class结构体的指针。结构体数据结构:

/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

struct objc_class {
    Class _Nonnull isa;                                          // objc_class 结构体的实例指针

#if !__OBJC2__
    Class _Nullable super_class;                                 // 指向父类的指针
    const char * _Nonnull name;                                  // 类的名字
    long version;                                                // 类的版本信息,默认为 0
    long info;                                                   // 类的信息,供运行期使用的一些位标识
    long instance_size;                                          // 该类的实例变量大小;
    struct objc_ivar_list * _Nullable ivars;                     // 该类的实例变量列表
    struct objc_method_list * _Nullable * _Nullable methodLists; // 方法定义的列表
    struct objc_cache * _Nonnull cache;                          // 方法缓存
    struct objc_protocol_list * _Nullable protocols;             // 遵守的协议列表
#endif

};

objc_class结构体存放的数据称为元数据
objc_class 结构体 的第一个成员变量是 isa 指针,isa 指针 保存的是所属类的结构体的实例的指针,这里保存的就是 objc_class 结构体的实例指针,而实例换个名字就是对象。换句话说,Class(类) 的本质其实就是一个对象,我们称之为类对象。

object(对象)

在“objc/objc.h”中,Object(对象)被定义为 objc_object 结构体,其数据结构如下:

/// Represents an instance of a class.
struct objc_object {
    Class _Nonnull isa;       // objc_object 结构体的实例指针
};

/// A pointer to an instance of a class.
typedef struct objc_object *id;

这里的 id 被定义为一个指向 objc_object 结构体 的指针。从中可以看出 objc_object 结构体 只包含一个 Class 类型的 isa 指针。
换句话说,一个 Object(对象)唯一保存的就是它所属 Class(类) 的地址。当我们对一个对象,进行方法调用时,比如 [receiver selector];,它会通过 objc_object 结构体的 isa 指针 去找对应的 objc_class 结构体,然后在 objc_class 结构体 的 methodLists(方法列表) 中找到我们调用的方法,然后执行。

Meta Class(元类)

Meta Class(元类) 就是一个类对象所属的 类。一个对象所属的类叫做 类对象,而一个类对象所属的类就叫做 元类。

Runtime 中把类对象所属类型就叫做 Meta Class(元类),用于描述类对象本身所具有的特征,而在元类的 methodLists 中,保存了类的方法链表,即所谓的「类方法」。并且类对象中的 isa 指针 指向的就是元类。每个类对象有且仅有一个与之相关的元类。

我们是通过对象的 isa 指针 找到 对应的 Class(类);然后在 Class(类) 的 method list(方法列表) 中找对应的 selector 。
而 类方法的调用过程 和对象方法调用差不多,流程如下:

通过类对象 isa 指针 找到所属的 Meta Class(元类);
在 Meta Class(元类) 的 method list(方法列表) 中找到对应的 selector;
执行对应的 selector。

比如这段代码:

NSString *testString = [NSString stringWithFormat:@"%d,%s",3, "test"];

上边的示例中,stringWithFormat: 被发送给了 NSString 类,NSString 类 通过 isa 指针 找到 NSString 元类,然后在该元类的方法列表中找到对应的 stringWithFormat: 方法,然后执行该方法。

实例对象、类、元类之间的关系

在这里插入图片描述

方法(method)

objc_class 结构体 的 methodLists(方法列表)中存放的元素就是 方法(Method)。

先看runtime中objc_method结构体的数据结构:


/// An opaque type that represents a method in a class definition.
/// 代表类定义中一个方法的不透明类型
typedef struct objc_method *Method;

struct objc_method {
    SEL _Nonnull method_name;                    // 方法名
    char * _Nullable method_types;               // 方法类型
    IMP _Nonnull method_imp;                     // 方法实现
};

  1. 首先来看方法名:SEL 是一个指向 objc_selector 结构体 的指针。SEL的意思同样在“消息传递与消息转发”的博客中有讲:iOS——消息传递和消息转发
  2. 其次是方法实现:IMP 的实质是一个函数指针,所指向的就是方法的实现。IMP用来找到函数地址,然后执行函数。IMP在“消息传递与消息转发”的博客中有讲:iOS——消息传递和消息转发
  3. 方法类型:方法类型 method_types 是个字符串,用来存储方法的参数类型和返回值类型。

因此,Method 就是将 SEL(方法名) 和 IMP(函数指针) 关联起来,当对一个对象发送消息时,会通过给出的 SEL(方法名) 去找到 IMP(函数指针) ,然后执行。

总结

runtime中主要还是涉及消息传递和消息转发的内容居多,因此想要更深入的了解runtime,可以再去看我的“消息传递和消息转发”这篇博客学习:iOS——消息传递和消息转发

  • 14
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
iOS Runtime是一种运行时环境,它是iOS操作系统中的重要组成部分。iOS Runtime为开发者提供了一套动态询问、修改和扩展应用程序行为的机制。 首先,iOS Runtime实现了Objective-C语言的动态特性。Objective-C是一种面向对象的编程语言,它具有动态特性,即在运行时能够动态地修改对象的行为。iOS Runtime允许开发者通过运行时系统对类、对象、方法以及属性进行动态操作。例如,开发者可以在运行时为某个类添加新的方法,也可以通过运行时修改类的实例变量。 其次,iOS Runtime还提供了消息发送机制。在Objective-C中,对象之间的通信是通过消息发送来完成的。iOS Runtime负责将消息转发给正确的接收者,并执行相应的方法。这个过程是动态的,开发者可以在运行时动态改变消息的接收者或方法的实现。这为Objective-C语言带来了很高的灵活性。 此外,iOS Runtime还支持方法的交换与替换。开发者可以通过运行时机制,在运行时将一个方法的实现替换为另一个方法的实现,或者交换两个方法的实现。这对于调试、性能监控和代码扩展都是非常有用的。 总结来说,iOS RuntimeiOS操作系统中实现Objective-C语言特性的核心组件。它提供了动态特性的支持,使开发者能够在运行时动态地修改类、对象和方法的行为,实现更加灵活和可扩展的应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值