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;                                                // 类的版本信息,默认为 0long 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——消息传递和消息转发

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/699989.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql主从热备部署

1、主从复制原理 mysql之间数据复制的基础是二进制日志文件。一台mysql数据库一旦开启用日志文件后,其作为master,它的数据库所有操作都会以事件的方式记录在二进制日志中,其他数据库作为slave通过一个I/O线程与主数据库保持通信,…

OpenAI 发布新款大型语言模型 GPT-4o,带大家了解最新ChatGPT动态。

OpenAI 发布新款大型语言模型 GPT-4o 昨日OpenAI 举办了一场线上活动,正式发布了其最新研发的 AI 模型 GPT-4o,并详细介绍了该模型的强大功能和未来发展规划。此次发布标志着 AI 技术的重大突破,为用户提供了更加便捷、高效的 AI 工具&#…

MySQL创建索引报错 Specified key was too long;max key length is 1000 bytes.

MySQL对创建索引的大小有限制,一般索引键最大长度总和不能超过1000个字节。 问题描述 MySQL创建索引时报错 Specified key was too long;max key length is 1000 bytes. 解决办法 (1) 修改存储引擎 InnoDB的索引字段长度限制大于MyISAM,可以尝试改成…

Pytorch学习-引言

Pytorch相关链接 Pytorch官方网站 https://pytorch.org/ Pytorch的Github仓库 https://github.com/pytorch/pytorch Pytorch论坛 https://discuss.pytorch.org/ Pytorch离线下载包链接 https://download.pytorch.org/whl/torch_stable.html Pytorch学习视频推荐链接 http://【…

记一次跨域问题

线上跨域问题,在自己配置确认没问题下,要及时找运维看看是不是nginx配置问题。 两个方面: 项目代码 nginx配置 SpringBoot 解决跨域问题的 5 种方案! SpringBoot解决CORS跨域问题 SpringBoot-实现CORS跨域原理及解决方案

2024 年第一季度全球互联网中断事件

2024 年第一季度伊始,互联网发生了多起中断事件。陆地和海底电缆的损坏在多个地方造成了问题,而与持续中地缘政治冲突相关的军事行动影响了其他地区的连接。 几个非洲国家以及巴基斯坦的政府下令关闭互联网,主要针对移动网络连接。 被称为Ano…

【机器学习】逻辑回归:智能垃圾邮件分类实例

逻辑回归:智能垃圾邮件分类的利器 一、引言二、逻辑回归概述三、垃圾邮件分类实例数据准备特征选择与建模 四、总结与展望 一、引言 随着互联网的迅猛发展,电子邮件已成为人们日常生活和工作中不可或缺的一部分。然而,与此同时,垃…

IDEA报错:java 找不到符号

IDEA报错:java 找不到符号,代码没问题,IDEA缓存也清理了也重新构建了就是不行 最后使用终极大法 -Djps.track.ap.dependenciesfalse

1146 -Table ‘performance schema.session variables‘ doesn‘t exist的错误解决

一、问题出现 今天在本地连数据库的时候,发现这个问题,哎呦我擦,差点吓死了 二、解决办法 1)找文件 用everything搜一下MySQL Server 5.7 然后去Windows服务找一下MySQL配置文件的具体路径 如果知道那最好,不知道那…

Leaflet系列——【一】初识Leaflet与Leaflet视图操作

初识Leaflet(vue3 ) 前言:当你熟悉了openlayer、mapbox、cesium等一些GIS框架之后,对于我们开发来说其实他们的本质就是往瓦片上面叠加图层、【点、线、面、瓦片、geoJson、热力图、图片、svg等等】都是一层层的Layer图层&#xf…

400元已到账,成交从认真开始

昨天发了一个值班的需求,收到了很多好友的响应,这里非常感谢关注创业程序员卡酷的老朋友、新朋友。今天分享一下:拓展、合作、成交 现在不管是IT行业还是其他行业,大环境可谓一片惨淡,35乃至30找不到工作的失业人员一抓…