iOS底层原理:Method Swizzling原理和注意事项(一)

简介: Method Swizzling的含义是方法交换,其核心内容是使用runtime api在运行时将一个方法的实现替换成另一个方法的实现。我们利用它可以替换系统或者我们自定义类的方法实现,进而达到我们的特殊目的,这就是我们常说的iOS黑魔法。

Method Swizzling 是什么?


Method Swizzling的含义是方法交换,其核心内容是使用runtime api在运行时将一个方法的实现替换成另一个方法的实现。我们利用它可以替换系统或者我们自定义类的方法实现,进而达到我们的特殊目的,这就是我们常说的iOS黑魔法。

本文Demo地址:Github-JQMethodSwizzling

Method Swizzling 原理


OC方法在底层是通过方法编号SEL函数实现IMP一一对应进行关联的。打个比方,OC类好比一本书,SEL就像是书中的目录,IMP相当于每条目录所对应的页码。关系如图所示:


image.png


方法交换的代码如下:

Method oriMethod = class_getInstanceMethod(cls, oriSEL);
    Method swiMethod = class_getInstanceMethod(cls, swiSEL);
    method_exchangeImplementations(oriMethod, swiMethod);

交换后的关系如图所示:


image.png

2.png

从上述方法交换可以看出:

  • 交换的是两者的方法实现,也就是说调用oriSEL方法时,最终走的方法实现是swiIMP;调用swiSEL方法时,最终走的方法实现是oriIMP
  • 由此可见,在进行方法交换操作时,如果交换代码调用了两次或多次(2的倍数),就会导致方法实现又交换了回去,相当于交换了个寂寞,所以交换代码建议放在单例下进行来保证方法交换的有效性。



方法交换在使用中的递归调用分析


首先,我们来创建一个JQStudent类,类中有两个实例方法,jq_studentInstanceMethodstudentInstanceMethod;然后,在load方法中对两个方法进行交换;最后,jq_studentInstanceMethod的实现中再次调用jq_studentInstanceMethod方法。

代码实现如下图:


image.png

我们看到,这里会在jq_studentInstanceMethod方法中再次调用该方法,会不会引起递归调用呢?

运行结果如下图:


image.png

从运行结果看,并没有引起递归。这是因为进行方法交换后,在执行[st studentInstanceMethod]时,实际上找到的是jq_studentInstanceMethod的方法实现,而jq_studentInstanceMethod方法实现中又执行[self jq_studentInstanceMethod],同样是因为方法交换,此时jq_studentInstanceMethod的方法实现也已经指向了studentInstanceMethod,所以并不会引起递归调用。相反,如果我们在jq_studentInstanceMethod方法中调用了[self studentInstanceMethod]才是会引起递归调用的,小伙伴们一定要注意!!!

流程如下图:

image.png

在实际的开发中,我们常采用这种方式对业务流程中的一些关键方法进行方法交换(俗称hook),从而达到不影响业务流程的情况下完成一些信息的收集工作,而这种方式则被称为AOPAspect Oriented Programming,面向切面编程)。AOP是一种编程的思想,区别于OOPObject Oriented Programming,面向对象编程)。其实OOPAOP都是一种编程的思想,只不过OOP编程思想更加倾向于对业务模块的封装,划分出更加清晰的逻辑单元。而AOP则是面向切面进行提取封装,提取各个模块中的公共部分,提高模块的复用率,降低业务之间的耦合性。




相关文章
|
7月前
|
存储 运维 安全
iOS加固原理与常见措施:保护移动应用程序安全的利器
iOS加固原理与常见措施:保护移动应用程序安全的利器
95 0
|
7月前
|
存储 运维 安全
iOS加固原理与常见措施:保护移动应用程序安全的利器
iOS加固原理与常见措施:保护移动应用程序安全的利器
161 0
|
C语言 索引
09-iOS之load和initialize底层调用原理分析
09-iOS之load和initialize底层调用原理分析
99 0
|
5月前
|
算法 iOS开发 C++
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); 的作用和注意事项
默认情况下,C++的输入输出流与C标准库的输入输出函数是同步的,这会造成一定的性能损失。:使用cin.tie(0)和cout.tie(0)可以取消cin与cout之间的绑定,这意味着在进行输入操作时,不需要强行刷新输出缓冲区。:如果你的程序在输入输出中同时使用了C++的输入输出流和C标准库的输入输出函数(如scanf和printf),则不应该使用这段代码。:在使用了这段代码后,应避免使用C标准库的输入输出函数(如printf和scanf),因为这些函数与输入输出流的同步已被关闭。这段代码的主要用途是。
216 1
|
7月前
|
安全 前端开发 数据安全/隐私保护
【教程】 iOS混淆加固原理篇
本文介绍了iOS应用程序混淆加固的缘由,编译过程以及常见的加固类型和逆向工具。详细讨论了字符串混淆、类名、方法名混淆、程序结构混淆加密等加固类型,并介绍了常见的逆向工具和代码虚拟化技术。
|
7月前
|
编解码 Android开发 iOS开发
iOS 上架审核宝典:注意事项与实用工具分享
iOS 上架审核宝典:注意事项与实用工具分享
|
7月前
|
安全 算法 前端开发
【完整版教程】iOS混淆加固原理篇
在iOS开发中,应用程序的安全性和保护显得尤为重要。由于iOS系统的开放性,一些逆向工具可以轻松地对应用程序进行反编译和分析,从而导致应用程序源代码、算法和敏感信息的泄露。为了保护应用程序的安全性,我们需要对应用程序进行混淆加固。本文将介绍iOS混淆加固的原理和常见的加固类型。
|
7月前
|
编解码 Android开发 iOS开发
iOS 上架审核宝典:注意事项与实用工具分享
iOS 上架审核宝典:注意事项与实用工具分享
|
7月前
|
JSON 安全 数据安全/隐私保护
​iOS Class Guard github用法、工作原理和安装详解及使用经验总结
​iOS Class Guard github用法、工作原理和安装详解及使用经验总结
109 0
|
7月前
|
安全 数据安全/隐私保护 iOS开发
【iOS开发】iOS App的加固保护原理:使用ipaguard混淆加固
【iOS开发】iOS App的加固保护原理:使用ipaguard混淆加固
101 0