OC Swizzle实战

前言:在项目中开发中会遇到编辑框触发编辑后白屏,或者其他方式触发出现白屏的情况.

通过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];

}

总结记录一下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值