runtime的消息交换

Method Swizzing

顾名思义,就是讲2个方法进行交换,由原来的  A---MethodA_A  B---Method_B,变为 A---Method_B  B---Method_A

Method Swizzing有什么用处呢?

比如说我们想统计每一个ViewController展示给用户的次数,我们可以在每个ViewController里的ViewDidApper里添加跟踪代码,但是这个过于麻烦,需要在每个ViewController里写重复的代码。
  • 我们可以创建一个子类,但是需要创建UIViewController、UITableViewController、UINavigationController以及UIKit里的ViewController的子类,同样会很麻烦
  • 在这种情况下我们就可以使用Method Swizzing

Method Swizzing相关函数介绍

1、获取一个方法的SEL

class_getInstanceMethod(Class _Nullable cls, SEL _Nonnull name)
  • 参数一:方法所在类
  • 参数二:方法名

2、获取一个方法的IMP

class_getMethodImplementation(Class _Nullable cls, SEL _Nonnull name) 

3、添加一个方法

class_addMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp, const char * _Nullable types) 
  • 参数一:添加方法所在类
  • 参数二:添加方法名
  • 参数三:指向一个方法实现的指针
  • 参数四:参数类型的说明(方法返回值,参数等信息)

4、用一个方法替换另外一个方法

class_replaceMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp, const char * _Nullable types)

5、交换方法

method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2)

Method Swizzling 注意要点

一、在+load()方法中实现

Objective-C在运行时会自动调用类的两个方法+load和+initialize。+load会在类初始加载时调用, +initialize方法是以懒加载的方式被调用的,如果程序一直没有给某个类或它的子类发送消息,那么这个类的 +initialize方法是永远不会被调用的。所以Swizzling要是写在+initialize方法中,是有可能永远都不被执行。

二、使用dispatch_once 中执行

    Swizzling会改变全局状态,所以在运行时采取一些预防措施,使用dispatch_once就能够确保代码不管有多少线程都只被执行一次。如果不写进行了偶数次的交换,就相当于没有交换。

参考文章:runtime 黑魔法 Method Swizzing http://zhangzr.cn/2018/02/06/iOS%E5%BC%80%E5%8F%91-runtime-%E9%BB%91%E9%AD%94%E6%B3%95Method-swizzling/

runtime 如何使用https://halfrost.com/how_to_use_runtime/

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容