在 Runtime 改变selector所对应的 imp 来达到让原有 method 实现其他功能的目的
如果在执行完IMPn后还想继续调用IMPc的话,只需要在IMPn中调用selectorN就行了。
==================================例1=================================
实现:捕获UIApplication 的openURL:方法 并用my_openURL:方法代替
#import "HookSwizzle.h"
#import <objc/runtime.h>
@implementation HookSwizzle
+ (void)setUp {
/*
在Objective-C中调用一个方法,其实是向一个对象发送消息,查找消息的唯一依据是selector的名字。
IMP有点类似函数指针,可理解为指向具体的Method实现。
捕获UIApplication 的openURL:方法
先给UIApplication添加方法my_openURL: 再设置openURL:方法的IMP为my_openURL:方法的IMP
*/
// 1.获取UIApplication类的openURL:方法
Method ori_Method = class_getInstanceMethod([UIApplication class], @selector(openURL:));
// 2.给UIApplication添加my_openURL:方法 入口为UIApplication类的openURL:方法的IMP
IMP ori_IMP = method_getImplementation(ori_Method);
class_addMethod([UIApplication class], @selector(my_openURL:), ori_IMP, method_getTypeEncoding(ori_Method));
// 3.给UIApplication类openURL:方法 设置为HookSwizzle类my_openURL:方法的IMP
IMP my_IMP = class_getMethodImplementation([HookSwizzle class], @selector(my_openURL:));
method_setImplementation(ori_Method, my_IMP);
}
- (BOOL)my_openURL:(NSURL *)url {
//url = [NSURL URLWithString:@"http://www.sina.com.cn/"];
NSLog(@"my_openURL:%@", url.absoluteString);
return [self my_openURL:url];
}
@end
测试使用://url = [NSURL URLWithString:@"http://www.sina.com.cn/"];可以捕获UIApplication 由打开百度网改为打开新浪网
- (IBAction)openURLAction:(UIButton *)sender {
[HookSwizzle setUp];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://www.baidu.com/"]];
}
==================================例2=================================
实现:通过交换UIApplication类的openURL:方法和HookSwizzle类my_openURL:方法的 IMP,捕获UIApplication 的openURL:方法 并用my_openURL:方法代替
#import "HookSwizzle.h"
#import <objc/runtime.h>
@implementation HookSwizzle
+ (void)setUp {
// 获取UIApplication的 openURL:方法
Method ori_Method = class_getInstanceMethod([UIApplication class], @selector(openURL:));
// 获取HookSwizzle的 my_openURL:方法
Method my_Method = class_getInstanceMethod([HookSwizzle class], @selector(my_openURL:));
// 给UIApplication添加 my_openURL:方法
IMP ori_IMP = class_getMethodImplementation([UIApplication class], @selector(openURL:));
class_addMethod([UIApplication class], @selector(my_openURL:), ori_IMP, method_getTypeEncoding(ori_Method));
// 交换openURL:方法 和 my_openURL:方法的 IMP
method_exchangeImplementations(ori_Method, my_Method);
}
- (BOOL)my_openURL:(NSURL *)url {
//url = [NSURL URLWithString:@"http://www.sina.com.cn/"];
NSLog(@"my_openURL:%@", url.absoluteString);
return [self my_openURL:url];
}