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.mzph.cn/bicheng/12254.shtml

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

相关文章

如何通过ETL工具对数据进行去重

在数据处理流程中,数据去重是一个至关重要的环节,它能够确保数据分析的准确性和效率。ETL(Extract, Transform, Load)工具作为数据集成的重要组成部分,提供了强大的功能来帮助用户实现数据的抽取、转换和加载&#xff…

高级查询(一)

解决需求&#xff1a;Excel都可以轻松搞定 分组查询原理&#xff1a; 语法&#xff1a; SELECT …<列名> FROM <表名> [WHERE<条件表达式> ] GROUP BY 参与分组的列 可以与 聚合函数作用的列 一块显示 注意 SELECT列表中只能包含&#xff1a; 1、被分…

算法-卡尔曼滤波之卡尔曼滤波的其他三个方程

一维不带噪声的卡尔曼滤波方程有五个&#xff0c;下面分析剩余的三个方程&#xff1a; 分析第一个例子&#xff0c;其中测量值和真实值之间的误差属于测量误差&#xff08;使用准确性来描述&#xff09;&#xff0c;由于测量误差是随机的&#xff0c;我们可以使用方差来描述&am…

Nginx 代理 MySQL 实现通过域名连接数据库

文章目录 Nginx 模块介绍Stream 模块配置远程连接 MySQLDataGrip 连接 MySQL Nginx 安装这里不做介绍。域名默认已经解析到服务器公网IP。 Nginx 模块介绍 HTTP 模块&#xff1a; HTTP模块提供了处理HTTP请求的功能&#xff0c;包括反向代理、负载均衡、缓存、HTTP代理等。 例…

搜索整个文件夹的所有日志

grep request * 这里的*就是全部文件 grep -e A -e b" * grep -rine "关键字"

遇到难题 暗区突围掉宝Twitch绑定关联账号显示404

Twitch作为一个广受欢迎的直播平台&#xff0c;经常会举办各种与游戏相关的互动活动&#xff0c;如“掉宝活动”&#xff0c;其中就包括了与《暗区突围》的合作。这类活动允许观众在观看指定的Twitch直播时&#xff0c;通过将他们的Twitch账号与《暗区突围》游戏账号绑定&#…

(二刷)代码随想录第6天|242.有效的字母异位词、349.两个数组的交集

242.有效的字母异位词 242. 有效的字母异位词 - 力扣&#xff08;LeetCode&#xff09; 代码随想录 (programmercarl.com) 学透哈希表&#xff0c;数组使用有技巧&#xff01;Leetcode&#xff1a;242.有效的字母异位词_哔哩哔哩_bilibili 给定两个字符串 s 和 t &#xff…

使用Pyramid、Mako和PyJade生成 HTML

Pyramid 是一个流行的 Python Web 框架&#xff0c;而 Mako 和 PyJade 是用于模板引擎的工具&#xff0c;它们可以与 Pyramid 配合使用来生成 HTML 内容。但是在实际使用中还是有些差别的&#xff0c;尤其会遇到各种各样的问题&#xff0c;下面我将利用我所学的知识一一为大家解…

Vue3组件库开发项目实战——03封装Button组件/输出vitePress文档

Vue3组件库开发项目实战——01组件开发必备知识导学-CSDN博客 Vue3组件库开发项目实战——02项目搭建&#xff08;配置Eslint/Prettier/Sass/Tailwind CSS/VitePress/Vitest&#xff09;-CSDN博客 在前面两篇博客中&#xff0c;我分别介绍了组件库开发必学知识&#xff0c;以及…

免费pr相册模板mogrt|手机壁纸AI绘画摄影作品照片展示模板视频素材

pr相册模板mogrt&#xff0c;手机壁纸、电脑桌面壁纸、AI绘画、摄影作品、照片展示模板视频素材。 Premiere Pro 2023及以上版本。 全高清&#xff08;19201080&#xff09;分辨率/30fps。 通用表达式&#xff08;适用于所有特效语言&#xff09;。 免费下载&#xff1a;https…

自动删除 PC 端微信缓存数据,包括从所有聊天中自动下载的大量文件、视频、图片等数据内容,解放你的空间。

Clean My PC Wechat 自动删除 PC 端微信自动下载的大量文件、视频、图片等数据内容&#xff0c;解放一年几十 G 的空间占用。 该工具不会删除文字的聊天记录&#xff0c;请放心使用。请给个 Star 吧&#xff0c;非常感谢&#xff01; 现已经支持 Windows 系统中的所有微信版本…

整合Tess4J图文识别技术

仓库地址&#xff1a;https://gitee.com/z3inc/tess4j-demo.git 1. OCR图文识别介绍 OCR&#xff08;全称 Optical Character Recognition&#xff0c;直译为光学字符识别&#xff09;用于图片文字识别&#xff0c;例如 提取图片中车牌号等等。 Java中实现OCR的技术方案有&…

DGC-GNN 配置运行

算法 DGC-GNN&#xff0c;这是一种全局到局部的图神经网络&#xff0c;用于提高图像中2D关键点与场景的稀疏3D点云的匹配精度。与依赖视觉描述符的方法相比&#xff0c;这种方法具有较低的内存需求&#xff0c;更好的隐私保护&#xff0c;并减少了对昂贵3D模型维护的需求。DGC-…

基于51单片机的时钟万年历—可农历显示

基于51单片机的时钟万年历 &#xff08;仿真&#xff0b;程序&#xff0b;原理图&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 1、可以显示年、月、日、时、分、秒、星期、农历&#xff1b; 2、按键可以设置闹钟及报警&#xff1b; 3、按键可以调整时…

[Java EE] 文件IO (二):文件内容读写-----数据流

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

(2024,MambaOut,Mamba 适合长序列,区分指标,不适合分类,适合检测和分割)视觉真的需要 Mamba 吗?

MambaOut: Do We Really Need Mamba for Vision? 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 简介 3. 概念讨论 3.1 Mamba 适合哪些任务&#xff1f; 3.2 视觉识别任…

echarts实现金价可视化大屏(项目实战)

前言 最近由于某种原因参加了一个比赛&#xff0c;三天时间肝出来一个可视化大屏项目&#xff08;无后端&#xff09;&#xff0c;代码已开源&#xff0c;但是还在比赛期间不知道会不会影响到 技术使用&#xff1a;html&#xff0c;css&#xff0c;js&#xff0c;echarts&#…

Jmeter+Grafana+Prometheus搭建压测监控平台

本文不介绍压测的规范与技术指标&#xff0c;本文是演示针对Jmeter如何将压测过程中的数据指标&#xff0c;通过Prometheus采集存储&#xff0c;并在Granfan平台进行仪表盘展示; 介绍 系统压测属于日常项目开发中的一个测试环节&#xff0c;使用测试工具模拟真实用户行为&…

Springboot+MybatisPlus如何实现分页和模糊查询

实现分页查询的时候我们需要创建一个config配置类 1、创建MybatisPlusConfig类 Configuration //表明这是一个配置类 ConditionalOnClass(Value{PaginationInterceptor.class} //ConditionalOnClass:当指定的类存在时&#xff0c;才会创建对应的Bean // 这里当PaginationInt…

Go-Zero定义API实战:探索API语法规范与最佳实践(五)

前言 上一篇文章带你实现了Go-Zero模板定制化&#xff0c;本文将继续分享如何使用GO-ZERO进行业务开发。 通过编写API层&#xff0c;我们能够对外进行接口的暴露&#xff0c;因此学习规范的API层编写姿势是很重要的。 通过本文的分享&#xff0c;你将能够学习到Go-Zero的API…