iOS Method Swizzling
前言
有个奇怪的需求:每个UIViewController在viewDidAppear:和viewWillAppear:方法中都需要执行一些操作。这里介绍一种iOS Method Swizzling方法:让viewDidAppear:和customViewDidAppear:方法调换实现方式;让viewWillAppear:和customViewWillAppear:方法调换实现方式。
实现过程
- 新建UIViewController的一个category - Swizzle
- 在Swizzle中实现customViewDidAppear:方法和customViewWillAppear:方法。
- 并且重写
load
方法,在load方法中将指向viewDidAppear:实现的指针和指向customViewDidAppear:实现的指针对调;将指向viewWillAppear:实现的指针和指向customViewWillAppear:实现的指针对调 - 函数指针对调实现
- 在AppDelegate.m中import这个Swizzle category。那么在所有的UIViewController执行load方法时都会执行Swizzle中重写的load方法,以实现方法的对调;所以之后正常调用viewDidAppear:或是viewWillAppear:时,其实是调用的customViewDidAppear:和customViewWillAppear:方法
具体代码实现
- Swizzle category
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24@implementation UIViewController (Swizzle)
+ (void)load {
swizzleAllViewController();
}
- (void)customViewDidAppear:(BOOL)animated {
// do something here
[self customViewDidAppear:animated]; // 其实是调用的viewDidAppear:
}
- (void)customviewWillAppear:(BOOL)animated {
// do something here
[self customviewWillAppear:animated]; // 其实是调用的viewWillAppear:
}
@end
// 函数指针对调
void swizzleAllViewController() {
Swizzle([UIViewController class], @selector(viewDidAppear:), @selector(customViewDidAppear:));
//Swizzle([UIViewController class], @selector(viewWillDisappear:), @selector(customViewWillDisappear:));
Swizzle([UIViewController class], @selector(viewWillAppear:), @selector(customviewWillAppear:));
} - 函数指针对调的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26void Swizzle(Class c, SEL origSEL, SEL newSEL) {
Method origMethod = class_getInstanceMethod(c, origSEL);
Method newMethod = nil;
if (!origMethod) {
origMethod = class_getClassMethod(c, origSEL);
if (!origMethod) {
return;
}
newMethod = class_getClassMethod(c, newSEL);
if (!newMethod) {
return;
}
} else {
newMethod = class_getInstanceMethod(c, newSEL);
if (!newMethod) {
return;
}
}
if (class_addMethod(c, origSEL, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) {
NSLog(@"vanney code log... errorhappened");
class_replaceMethod(c, newSEL, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
} else {
method_exchangeImplementations(origMethod, newMethod);
}
}
P.S
以上代码都参考自Coding-iOS
参考
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.