美文网首页
iOS 无代码入侵的方法hook

iOS 无代码入侵的方法hook

作者: 易木 | 来源:发表于2017-06-29 09:58 被阅读249次

    *于是App端在某些页面切换,交互操作的时候需要给统计系统发送一条消息在几十个Controller 的项目里,一个一个地加代码那完全是不可能的,维护起来也是吃力,但这里需要处理的是 Controller, 可以有以下方式实现上述需求

    (1). 利用Objective-C 中的对象继承
    • 继承 在面向对象开发中是非常常用的,像我们现在做的项目工程中都会有一个BaseViewController,
    • 所有新建的ViewController都继承BaseViewController,通过往BaseViewController中添加一些公共方法\属性 可以被他们的子类所调用
    • 这是统一我们工程中所有视图控制器样式的一个主要途径
    (2). 利用Category 和Runtime实行方法hook
    • hook方案有一个好处,就是可以避免代码入侵,做到更加广泛的通用性.通过swizzling我们可以将原method与自己加入的method相结合,即不需要在原有工程中加入代码,又能做到全局覆盖

    • 既然用到hook方案,又要用runtime 的swizzling
    • 首先 新建一个UIViewController 的category
    • 实现swizzling代码
     + (void)load{
        [super load];
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            // 假如要打开controller的统计 ,则把下面这行代码打开
            __gbh_tracer_swizzleMethod([self class], @selector(viewDidAppear:), @selector(__gbh_tracer_viewDidAppear:));
        });
    }
    
    • 嗯,看到这里大家会发现 这里调用的是一个C的方法,然而这个C方法是怎么实现的呢?看下面
    void __gbh_tracer_swizzleMethod(Class class, SEL originalSelector, SEL swizzledSelector){
        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
        
        BOOL didAddMethod =
        class_addMethod(class,
                        originalSelector,
                        method_getImplementation(swizzledMethod),
                        method_getTypeEncoding(swizzledMethod));
        
        if (didAddMethod) {
            class_replaceMethod(class,
                                swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    }
    
    • 这是一个标准的swizzling写法,当然了 github上面也有关于swizzling的开源库,用起来也顺手 这里就不多说
    • 看回第一块代码,红色的viewDidAppear是即将被我hook的方法,__gbh_tracer_viewDidAppear 则是我需要实现的方法
    - (void)__gbh_tracer_viewDidAppear:(BOOL)animated{
        [self __gbh_tracer_viewDidAppear:animated];  //由于方法已经被交换,这里调用的实际上是viewDidAppear:方法
        
       //设置不允许发送数据的Controller
        NSArray *filter = @[@"UINavigationController",@"UITabBarController"];
        NSString *className = NSStringFromClass(self.class);
        if ([filter containsObject:className]) return ; //如果该Controller在不允许发送log的列表里,则不能继续往下走
       
        if ([self.title isKindOfClass:[NSString class]] && self.title.length > 0){ //有标题的才符合我的要求
            // 这里发送log
        }
    
    }
    

    相关文章

      网友评论

          本文标题:iOS 无代码入侵的方法hook

          本文链接:https://www.haomeiwen.com/subject/guqmcxtx.html