iOS 黑魔法 Method Swizzling
UIViewController 的 Category
#import "UIViewController+Test.h"
#import <objc/runtime.h>
@implementation UIViewController (Test)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method originalMethod = class_getInstanceMethod(self, @selector(viewWillAppear:));
Method swizzledMethod = class_getInstanceMethod(self, @selector(hook_viewWillAppear:));
method_exchangeImplementations(originalMethod, swizzledMethod);
});
}
- (void)hook_viewWillAppear:(BOOL)animated {
NSLog(@"开始埋点 0");
[self hook_viewWillAppear:animated];
NSLog(@"开始埋点 1");
}
@end
ViewController 继承自 ViewControllerB
ViewControllerB 继承自 ViewControllerC
在 ViewController.m 引入 #import "UIViewController+Test.h" 文件
然后在ViewController、ViewControllerA、ViewControllerB 修改代码如下:
- (void)viewDidLoad {
NSLog(@"%s -----> 1",__func__);
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"%s -----> 2",__func__);
}
运行程序,输出下面结果:
-[ViewController viewDidLoad] -----> 1
-[ViewControllerB viewDidLoad] -----> 1
-[ViewControllerA viewDidLoad] -----> 1
-[ViewControllerA viewDidLoad] -----> 2
-[ViewControllerB viewDidLoad] -----> 2
-[ViewController viewDidLoad] -----> 2
开始埋点 0
开始埋点 1
同类不同Category同一个方法的注意
不能名字一样
如:
#import "UIViewController+Test2.h"
#import <objc/runtime.h>
@implementation UIViewController (Test2)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method originalMethod = class_getInstanceMethod(self, @selector(viewWillAppear:));
Method swizzledMethod = class_getInstanceMethod(self, @selector(hook_viewWillAppear2:));
method_exchangeImplementations(originalMethod, swizzledMethod);
});
}
- (void)hook_viewWillAppear2:(BOOL)animated {
NSLog(@"开始埋点2 0");
[self hook_viewWillAppear2:animated];
NSLog(@"开始埋点2 1");
}
@end
有点好奇怪,即使不引入,UIViewController+Test2.h,也会自动引入,不知道是不是因为引入了UIViewController+Test.h,导致自动引入。。。
假如两个文件的方法:- (void)hook_viewWillAppear:(BOOL)animated 都一样,将不会执行,不一样就会一起执行。
-[ViewController viewDidLoad] -----> 1
-[ViewControllerB viewDidLoad] -----> 1
-[ViewControllerA viewDidLoad] -----> 1
-[ViewControllerA viewDidLoad] -----> 2
-[ViewControllerB viewDidLoad] -----> 2
-[ViewController viewDidLoad] -----> 2
开始埋点 0
开始埋点2 0
开始埋点2 1
开始埋点 1