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/
网友评论