iOS 为何使用runtime方法交换多次后却能按照交换顺序依次执行代码逻辑?
题目: 假设我们有一个ViewController,
Category A(ViewController),
Category B(ViewController),
Category C(ViewController)
4个文件, 其中3个category中都实现了自定义viewDidLoad方法, 会对ViewController中的ViewDidLoad方法进行方法替换, 那么依次替换后(A B C)的方法执行顺序是什么呢?
记method_exchangeImplementations(Method _Nonnullm1, Method _Nonnullm2) 方法多次执行的代码执行逻辑.
假设我们的方法替换由我们指定的一个category D来完成3次交换过程,代码如下图

那么接下来我们就详细来探究一下每次追加一个方法交换,会对原方法有什么改变。
1. IMP方法实现交换
第一趟: 交换 原方法 和 A

ViewController的原方法如下

在category A中方法如下:

交换后类实例方法和IMP的指向如下:

方法调用:
交换后, 调用class 0(ViewController)的selector0, 会调用category A的IMP1, 既打印 “extension A viewDidLoad”, 然后调用了category A的Sel, 就会去执行 class 0(ViewController)的IMP, 既打印 “origin viewDidLoad method”;
控制台打印如下:

接下来追加方法交换: 在原有方法交换基础上 追加 交换原方法 和 B

在category B中方法如下:

交换后类实例方法和IMP的指向如下:

代码执行: 执行Sel0—>IMP2—>SelB—>IMP1—>SelA—>IMP, 所以控制台输入顺序为 B A 0
控制台输出如下:

继续追加方法交换: 在原有方法交换基础上 追加 交换原方法 和 C

在category C中方法如下:

交换后类实例方法和IMP的指向如下:

代码执行: 先执行Sel0-->IMP3—>SelC—>IMP2—>SelB—>IMP1—>SelA—>IMP, 所以控制台输入顺序为 C B A 0
控制台输出如下:

由此可以推理出来:
我们依次追加n个对原方法交换, 那么class 0对应的Sel0执行的IMP会偏移指向最后一个方法交换的Sel, 那么就会按照交换前后顺序执行逻辑.
Demo地址: https://github.com/Winerywine/MethodExchange.git
iOS 为何使用runtime方法交换多次后却能按照交换顺序依次执行代码逻辑?的更多相关文章
- iOS运行时Runtime浅析
运行时是iOS中一个很重要的概念,iOS运行过程中都会被转化为runtime的C代码执行.例如[target doSomething];会被转化成objc)msgSend(target,@select ...
- iOS运行时 -- Runtime(摘抄自网络)
运行时(iOS) 一.什么是运行时(Runtime)? 运行时是苹果提供的纯C语言的开发库(运行时是一种非常牛逼.开发中经常用到的底层技术) 二.运行时的作用? 能获得某个类的所有成员变量 能获得某个 ...
- iOS:学习runtime的理解和心得 (转)
Runtime是想要做好iOS开发,或者说是真正的深刻的掌握OC这门语言所必需理解的东西.最近在学习Runtime,有自己的一些心得,整理如下, 一为 查阅方便 二为 或许能给他人一些启发, 三为 希 ...
- iOS - 回顾总结Runtime原理及使用
runtime简介 因为Objc是一门动态语言,所以它总是想办法把一些决定工作从编译连接推迟到运行时.也就是说只有编译器是不够的,还需要一个运行时系统 (runtime system) 来执行编译后的 ...
- iOS开发系列-Runtime运用场景
概述 Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码,底层都是基于它来实现的. 调用runtimeAPI需要导入都文件#impor ...
- iOS:学习runtime的理解和心得
http://www.cocoachina.com/ios/20150901/13173.html 作者:兴宇是谁 授权本站转载. Runtime是想要做好iOS开发,或者说是真正的深刻的掌握OC这门 ...
- iOS开发之Runtime使用
runtime简介 RunTime简称运行时.OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制. 对于C语言,函数的调用在编译的时候会决定调用哪个函数. 对于OC的函数,属于动态 ...
- iOS中利用 runtime 一键改变字体
1.准备 我们新建一个项目名叫ChangeFont,然后我就随便找了个名叫loveway.ttf的字体库拖进去,里面的工程目录大概就是这样的 目录 现在我们就简单的直接在storyboard上拖了一个 ...
- IOS 高级开发 runtime(二)
二.移魂大法 使用runtime还可以交换两个函数.先贴上代码和执行结果. #import <Foundation/Foundation.h> @interface DZLPerson : ...
随机推荐
- 针对base64编码和URIEncode的一点研究
Base64编码的作用 将任意的二进制比特串编码成由ASCii码中的64个可显示字符组成的字符串. 为什么需要base64编码? 所有的文件,本质上都是0.1组成的比特串,文本文件.二进制文件的区别只 ...
- 使用 Redis 进行阅读数统计并定时持久化
之前,统计每篇博文的阅读数的方式是经过筛选去重之后直接更新数据库,并发压力直接传导到数据库,假设1秒有1000个并发请求,传统方案会在1秒内并发进行1000次数据库更新操作. 为了降低数据库的并发压力 ...
- 基于H7的中移动物联例子以及简易操作说明,方便电脑端和手机端远程查看数据
说明: 1.操作前,务必优先看此贴里面的基础例子,先将WIFI连接到路由器上,这样才可以访问外网: https://www.cnblogs.com/armfly/p/11307803.html 2.有 ...
- JS中遍历对象属性的四种方法
Object.keys().Object.values().Object.entries().for...in.Map (1)Object.keys(): let ex1 = {c1: 'white' ...
- Promise代码详解(show you the code)
认识异步函数 同步函数: const sum1 =(a,b)=>{ return a+b } console.log('AAA'); console.log(sum(5,6)); conosle ...
- ABAP里SELECT的用法汇总(转)
通常使用Open SQL的数据查询语句SELECT将数据库条目选择到内存.一.SELECT语句:1)SELECT用于确定读取数据表中的哪些字段:2)FROM子句用于确定从哪些内表或者视图中读取数据:3 ...
- Linux - CentOS 7 安装 .Net Core 运行环境
阿里云的CentOS 7.7 64位,所需要的环境:MySql 5.7,.Net Core 2.2 ,Nginx 我这里用的 Xshell 工具,首先用root进入系统 版本信息 打开终端输入命令: ...
- C++调用bat并实现传值
1.设置环境变量,这一类为路径 C++ void bat(const string& sDirC, const string& sDirD) { char Ddir[256]; Ddi ...
- js-02-循环语句
循环语句分类{ for while do ( ) while } 一.for循环语句和for循环的嵌套 for循环格式eg: <script> var sim = 0; for(var i ...
- diango中的MTV——FBV/CBV以及装饰器的复用问题解决
MVC M: model 模型 与数据库交互 V: view 视图 HTML C:controller 控制器 流程 和 业务逻辑 MTV M:model ORM T:template 模板 HTML ...