美文网首页iOS 开发进化
IOS实现无埋点技术

IOS实现无埋点技术

作者: hard_coder | 来源:发表于2017-03-15 14:53 被阅读2236次

    技术方案实现的背景:

    因为在开发项目的时候,埋点都是手动埋的,每次业务需求的改变都要到处埋点,这就免不了会遗漏埋点。每次在发版之前,大数据的人都会跑过来说某个点没有埋,哎,不仅开发效率变低,而且手动埋点真的好痛苦。在老大的提议下,决定学习一下无埋点技术,来解决我们现在的埋点的现状。经过几番查找资料,大致实施方案是采用运行时的方法交换来进行方法的替换,在需要埋点的地方先埋入点,然后再执行原方法,使得埋点从业务中抽离出来。

    技术方案:(现在技术方案只是局限于不与业务逻辑挂钩的埋点,与业务挂钩的埋点还没有想到好的解决方案)

    在项目中需要埋入的点大约分为两大类:

    第一种:click事件

    click事件中大致又分为button的点击事件,手势的点击事件,还有例如tableView的代理点击事件。首先对于button的点击事件,写一个button的分类,在分类中重写load方法,在load方法中进行方法的替换,然后替换button的点击事件-(void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents ,在替换之后的方法中进行埋点的处理,然后再调用原来的点击事件的方法。这样悄悄地埋入了埋点,又不改变之前代码的逻辑。因为UIButton是继承自UIControl的,所以也可以写UIControl的分类,凡是继承自UIControl的控件的响应事件最后都会走-(void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event此方法,可以将此方法进行替换。但是采用这种给控件写分类的模式不是太喜欢,我需要给项目中所有涉及到click事件的控件写分类,例如button,得写button的分类进行事件的替换,tableView的代理方法的替换得写tabView的分类,碍于这种繁琐,我的解决方案是写UIViewController的分类,给UIViewController中的ViewWillAppear方法进行替换,下面就是重点讲解方法的替换的实现啦,好啦,上代码来解释吧!

    import "UIViewController+statistic.h"

    import "LFDZHSwizzleTool.h"

    import "LFDStatistic.h"

    @implementation 

    UIViewController (statistic)

    + (void)load{    

    static dispatch_once_t dispatch_once_token;    dispatch_once(&dispatch_once_token, ^{      

      SEL originlSelector = @selector(viewDidAppear:);        

    SEL newSelector = @selector(swizzleviewWillAppear:);    

    //此处是我封装的方法交换的方法

        [LFDZHSwizzleTool zhSwizzleWithOrigionClass:[self class] originalSelector:originlSelector swizzleClass:[self class] swizzleSelector:newSelector];    });

    }

    - (void)swizzleviewWillAppear:(BOOL)animated{    

    //加载plist    

    NSString *pathString = [[NSBundle mainBundle]pathForResource:@"buttonStatistics" ofType:@"plist"];    

    //获取加载plsit的字典    

    NSDictionary *plistDic = [NSDictionary dictionaryWithContentsOfFile:pathString];  

      //获取当前类的方法列表    NSDictionary *classMthodDic = plistDic[NSStringFromClass([self class])];  

      //如果没有获取就返回    if (classMthodDic == nil) return; // 该类的方法不需要hook   

     //获取方法的所有的key值,放到数组当中    NSArray *methodNameArray = [classMthodDic allKeys];   

     //遍历所有的方法    

    for (NSString *methodString in methodNameArray) {        

    __block SEL originalSEL = NSSelectorFromString(methodString);       

     // 这里需要判断是否是UIControl的事件,以防止两个地方同时hook,造成重复上传       

     BOOL isResponseOriginSEL = [self respondsToSelector:originalSEL];      

      //如果该类中有此方法那么就替换该类中的方法        

    if (isResponseOriginSEL) {           

    //使用aspect替换类中的方法  ,aspect是一个封装好的用来交换方法的第三方的框架,可以去gitHub上去下载      

     [[self class] aspect_hookSelector:originalSEL withOptions:AspectPositionAfter usingBlock:^(idinfo){

    NSString *selectorName = NSStringFromSelector(originalSEL);

    NSString *pathString = [[NSBundle mainBundle]pathForResource:@"buttonStatistics" ofType:@"plist"];

    NSDictionary *plistDic = [NSDictionary dictionaryWithContentsOfFile:pathString];

    // 2.获取某个类的方法列表

    NSDictionary *classMthodDic = plistDic[NSStringFromClass([self class])];

    // 3.获取其中某个方法的参数列表

    NSDictionary *parameterDic = classMthodDic[selectorName];

    NSString *eventID = parameterDic[@"eventID"];

    NSString *tarPageID = parameterDic[@"tarPageID"];

    //在此处上报需要埋入的点

    [LFDStatistic lfd_clickName:eventID tar_page_name:tarPageID params:nil];

    }

    error:nil];

    }

    }

    [self swizzleviewWillAppear:animated];

    }

    plist表:

    主要实现逻辑:给每个控制器的ViewWillAppear方法进行替换,在类中检索是否有plist表中需要埋入的点,如果有,就替换方法,在替换的方法中进行埋点。

    第二种:expose事件

    项目中因为所有的控制器都继承自一个baseVc,所以统一在baseVc的viewWillAppear方法中埋入expose事件。当然也可以在交换的方法中进行埋入。

    以上只是解决了简单的不涉及业务的click事件,在接下来的日子里会继续跟踪更好的方法来解决这个问题。以上文章的实录要感谢来自简书上的简友。

    埋点资料:https://github.com/Vienta/VIAnalyticsKit/blob/master/VIAnalyticsKit/Class/VIAnalyticsAOP.m

    相关文章

      网友评论

      • 1cdb19c230be:你好 很喜欢你的思路 可以给我看看你的plist具体怎么写的吗
      • SoolyChristina:方法交换后 你是怎么区分每个Controller的。。
        方法交换后 你是怎么区分每个button的。。
        能不能分享一下方案。

      本文标题:IOS实现无埋点技术

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