前言:在项目中开发中会遇到编辑框触发编辑后白屏,或者其他方式触发出现白屏的情况.
通过UI栈追踪器,看到很多视图控制器叠加在一起,不好入手排查,想想有没有其他方式进行更加高效排查呢?
开始从视图控制器生命周期的角度去排查,bug显示就是那一瞬间白屏,视图控制器其中有两个很重要的方法viewDidLoad和viewWillAppear方法,可以捕获并替换成自己写的方法然后自己进行排查操作.
关键流程:捕获到方法-交换方法-处理新的方法
@implementation UIViewController (sayHello)
+ (void)load {
SEL originalSelector = @selector(viewDidAppear:);
SEL swizzledSelector = @selector(swizzled_viewDidAppear:);
// class_getInstanceMethod方法得到Method类型
Method originalMethod = class_getInstanceMethod([self class], originalSelector);
Method swizzledMethod = class_getInstanceMethod([self class], swizzledSelector);
// method_exchangeImplementations交换映射指针
method_exchangeImplementations(originalMethod, swizzledMethod);
}
- (void)swizzled_viewDidAppear:(BOOL)animated {
[self swizzled_viewDidAppear:animated];
NSLog(@"hello, my name is %@", NSStringFromClass([self class]));
}
@end
关键代码:
新建 NSObject+Swizzle类以及UIViewController+hook类
[self swizzleMethod:@selector(viewDidLoad) swizzledSelector:@selector(__viewDidLoad)];
[self swizzleMethod:@selector(viewWillAppear:) swizzledSelector:@selector(fr_viewWillAppear:)];
+ (void)swizzleMethod:(SEL)originalSEL swizzledSelector:(SEL)swizzledSEL {
Class class = [self class];
//原有方法
Method originalMethod = class_getInstanceMethod(class, originalSEL);
//替换原有方法的新方法
Method swizzledMethod = class_getInstanceMethod(class, swizzledSEL);
//先尝试給源SEL添加IMP,这里是为了避免源SEL没有实现IMP的情况
// 方法的实现
IMP originalIMP = method_getImplementation(originalMethod); //class_getMethodImplementation(class, originalSEL);
IMP swizzledIMP = method_getImplementation(swizzledMethod);//class_getMethodImplementation(class, SwizzledSEL);
// 是否添加成功方法:添加了初始方法,实现内容指向目标方法体
BOOL isSuccess = class_addMethod(class, originalSEL, swizzledIMP, method_getTypeEncoding(swizzledMethod));
if (isSuccess) {
// 初始指向目标,那么把目标的内容指向初始
class_replaceMethod(class, swizzledSEL, originalIMP, method_getTypeEncoding(originalMethod));
}
else{
// 没有添加成功说明已经存在,就交换
// 注意,这里交换的是IMP 实现
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
新的方法进行判断
- (void)fr_viewWillAppear:(BOOL)animated{
NSLog(@"🍓🍓🍓 当前控制器 : %@",NSStringFromClass([self class]));
[self fr_viewWillAppear:animated];
}
fr_viewWillAppear 方法中获取到出现白屏的视图控制器 然后在__viewDidLoad方法中进行过滤和背景色处理
- (void)__viewDidLoad{
NSArray *arr = @[@"UIEditingOverlayViewController",@"UIInputWindowController",@"UICompatibilityInputViewController",@"UIApplicationRotationFollowingControllerNoTouches"];
if(![arr containsObject:NSStringFromClass(self.class)]){
self.view.backgroundColor = UIColor.whiteColor;
}
[self __viewDidLoad];
}
总结记录一下