Method Swizzling
Method Swizzling,又称动态方法交换,本质上是通过交换SEL和IMP的对应关系,从而实现实现方法的互换。
在OC中,每一个Method类的对象都对应了一个方法。每一个Method的实例对应的都有一个objc_method的结构体:
1 | typedef struct objc_method *Method; |
其中method_name表示的就是方法名,method_types表示的是方法类型,而method_imp表示的是方法的地址,因此Method Swizzling就是通过交换method_imp来实现方法的交换。
实现方法
1 | + (void)load |
注意点
-
方法的交换应该放在load中进行,而不应该放在init中,因为不管你是否初始化对象,OC总是会调用load函数,而且不需要调用[super load]以避免发生多次交换;
-
需要把交换放在dispatch_once中,这样可以始终保证只交换一次;
-
在新的函数实现中仍需要调用[self swizzledFunc],注意这里并不会产生死循环,因为进入到这个方法内部的时候,实际上调用的是originalFunc对应的函数实现,也就是相当于调用了原来函数的实现,然后就可以在这个实现的上下文中添加自己想要的实现代码;
-
可能产生由于子类未实现父类的函数导致的父类的函数方法被篡改的情况;
-
注意不要产生命名冲突。
更好的实现方法
1 | // 这里的id都可以改成对应的类型,或者在函数内部强转 |
FishHook
FishHook主要用于hook系统的函数,可以用来修改method_exchangeImplementations函数从而防止别人hook我们的函数。
- 首先要下载并引入fishhook.c和fishhook.c
- 编写hook函数,示例如下:
1 | static void (*orig_nslog)(NSString *, ...); |