美文网首页
iOS无埋点数据统计实验

iOS无埋点数据统计实验

作者: Jneth | 来源:发表于2017-07-06 11:23 被阅读0次

    项目中需要统计的数据包括

    1.在某个页面的停留时间(针对UIViewController)
    2.某个事件(method)触发的次数
    3.某个View的展示次数
    (目前属于试验阶段)

    1.停留时间runtime swap viewDidAppear & viewDidDisAppear

    #import "UIViewController+JHswizzling.h"
    static NSDate *startDate;
    @implementation UIViewController (JHswizzling)
    + (void)load{
        
        
        // 通过class_getInstanceMethod()函数从当前对象中的method list获取method结构体,如果是类方法就使用class_getClassMethod()函数获取。
        Method fromMethod = class_getInstanceMethod([self class], @selector(viewDidAppear:));
        Method toMethod = class_getInstanceMethod([self class], @selector(JH_swizzlingViewDidAppear));
        /**
         *  我们在这里使用class_addMethod()函数对Method Swizzling做了一层验证,如果self没有实现被交换的方法,会导致失败。
         *  而且self没有交换的方法实现,但是父类有这个方法,这样就会调用父类的方法,结果就不是我们想要的结果了。
         *  所以我们在这里通过class_addMethod()的验证,如果self实现了这个方法,class_addMethod()函数将会返回NO,我们就可以对其进行交换了。
         */
        if (!class_addMethod([self class], @selector(JH_swizzlingViewDidAppear), method_getImplementation(toMethod), method_getTypeEncoding(toMethod))) {
            method_exchangeImplementations(fromMethod, toMethod);
        }
        
        // 通过class_getInstanceMethod()函数从当前对象中的method list获取method结构体,如果是类方法就使用class_getClassMethod()函数获取。
        Method fromMethodDis = class_getInstanceMethod([self class], @selector(viewDidDisappear:));
        Method toMethodDis = class_getInstanceMethod([self class], @selector(JH_swizzlingViewDidDisAppear));
    
        if (!class_addMethod([self class], @selector(JH_swizzlingViewDidDisAppear), method_getImplementation(toMethodDis), method_getTypeEncoding(toMethodDis))) {
            method_exchangeImplementations(fromMethodDis, toMethodDis);
        }
    }
    
    // 我们自己实现的方法,也就是和self的viewDidAppear方法进行交换的方法。
    - (void)JH_swizzlingViewDidAppear{
        
        NSString *str = [NSString stringWithFormat:@"%@", self.class];
        // 我们在这里加一个判断,将系统的UIViewController的对象剔除掉
        NSDictionary *data = [self getJsonData];
        if ([[data allKeys]containsObject:str]) {
            
            if(![str containsString:@"UI"]){
                startDate = [NSDate  date];
                NSLog(@"统计打点出现 : %@ time : %@", [self getJsonData][str] ,startDate);
            }
        }
        
        [self JH_swizzlingViewDidAppear];
    }
    
    // 我们自己实现的方法,也就是和self的viewDidDisAppear方法进行交换的方法。
    - (void)JH_swizzlingViewDidDisAppear{
        NSString *str = [NSString stringWithFormat:@"%@", self.class];
        // 我们在这里加一个判断,将系统的UIViewController的对象剔除掉
        NSDictionary *data = [self getJsonData];
        if ([[data allKeys]containsObject:str]) {
            if(![str containsString:@"UI"]){
                //计算时间差
                NSDate *endDate = [NSDate date];
                NSTimeInterval duration = [endDate timeIntervalSinceDate:startDate];
                NSLog(@"统计打点出现 : %@ time : %f 时长", data[str] ,duration);
                //组合数据并存入数据库
                NSDictionary *vcDic = @{@"viewControllerCodeName":str,
                                           @"viewControllerName":data[str],
                                           @"viewControllerTime":[NSString stringWithFormat:@"%f",duration],
                                           };
                [JH_AnalyseDataHelper _AnalyseWithData:vcDic withType:AnalyseTypeViewController];
                
            }
        }
        
        [self JH_swizzlingViewDidDisAppear];
    }
    
    -(NSDictionary *)getJsonData{
        NSString *filePath = [[NSBundle mainBundle]pathForResource:@"analyse" ofType:@"json"];
        NSData *jsonData = [NSData dataWithContentsOfFile:filePath];
        NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableLeaves error:nil];
        
        return dic[@"viewController"];
    }
    

    2.某个事件(method)触发的次数,针对系统控件

    #import "JHAnalyseControlAnalyseNode.h"
    
    @implementation JHAnalyseControlAnalyseNode
    +(void)load{
        Method JH_sendAction = class_getInstanceMethod([UIControl class], @selector(sendAction:to:forEvent:));
        class_addMethod([UIControl class], @selector(JHhook_sendAction:to:forEvent:), method_getImplementation(JH_sendAction), method_getTypeEncoding(JH_sendAction));
        method_setImplementation(JH_sendAction, class_getMethodImplementation([self class], @selector(JHhook_sendAction:to:forEvent:)));
        
        
    }
    /**
     替换的方法
     */
    -(void)JHhook_sendAction:(SEL)action to:(nullable id)target forEvent:(nullable UIEvent *)event{
        
        NSString *methodName = NSStringFromSelector(action);
        NSString *className = [NSString stringWithUTF8String: object_getClassName(target)];
        UIControl *sender = (UIControl *)self;
        //第一层,视图ClassName
        NSDictionary *data = [[JHAnalyseControlAnalyseNode class]getJsonData];
        if ([[data allKeys]containsObject:className]) {
            //第二层,Action
            NSDictionary *class = data[className];
            if([[class allKeys]containsObject:methodName]){
                NSDictionary *action = class[methodName];
                
                NSString *tag = [NSString stringWithFormat:@"%ld",sender.tag];
                if([[action allKeys]containsObject:tag]){
                    NSDictionary *oneAction = action[tag];
                    NSLog(@"mtthodName=%@,className=%@,classRealName=%@tag=%@",methodName,className,oneAction[@"name"],tag);
                    //使用当前时间表示最后操作时间
                    NSDate *date = [NSDate date];
                    
                    NSTimeZone *zone = [NSTimeZone systemTimeZone];
                    
                    NSInteger interval = [zone secondsFromGMTForDate: date];
                    
                    NSDate *localeDate = [date  dateByAddingTimeInterval: interval];
                    
                    //组合数据并存入数据库
                    NSDictionary *eventDic = @{@"eventClass":className,
                                               @"eventCodeName":methodName,
                                               @"eventCount":@"1",
                                               @"eventDate":[NSString stringWithFormat:@"%@",localeDate],
                                               @"eventName":oneAction[@"name"],
                                               @"eventTag":tag,
                                               @"eventUser":@"jianghong",
                                               };
                    [JH_AnalyseDataHelper _AnalyseWithData:eventDic withType:AnalyseTypeEvent];
                }
            }
        }
        
        [self JHhook_sendAction:action to:target forEvent:event];
        
    }
    +(NSDictionary *)getJsonData{
        NSString *filePath = [[NSBundle mainBundle]pathForResource:@"analyse" ofType:@"json"];
        NSData *jsonData = [NSData dataWithContentsOfFile:filePath];
        NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableLeaves error:nil];
        
        return dic[@"event"];
    }
    

    配置的json文件(这个json文件最终将会配置到服务端作为下载数据)

    {
        "viewController":{
            "JHChatBaseController":"聊天主页面",
            "JHMapLocationVC":"定位",
            "JHChildMessageVC":"消息",
            "JHChildFriendsVC":"好友",
            "JHNoteVC":"广场",
            "JHSquareVC":"笔记"
        },
        "event":{
            "JHInputView":{
                "_additionButtonAction:":{
                    "0":{
                        "class":"JHInputView",
                        "event":"_additionButtonAction:",
                        "tag":"0",
                        "name":"录音"
                    },
                    "1":{
                        "class":"JHInputView",
                        "event":"_additionButtonAction:",
                        "tag":"1",
                        "name":"相册"
                    },
                    "2":{
                        "class":"JHInputView",
                        "event":"_additionButtonAction:",
                        "tag":"2",
                        "name":"相机"
                    },
                    "3":{
                        "class":"JHInputView",
                        "event":"_additionButtonAction:",
                        "tag":"3",
                        "name":"定位"
                    }
                },
                "_sendAction":{
                    "0":{
                        "class":"JHInputView",
                        "event":"_sendAction",
                        "tag":"0",
                        "name":"发送信息"
                    }
                }
            },
            "JHChatBaseCellVoice":{
                "onPlayButton:":{
                    "0":{
                        "class":"JHChatBaseCellVoice",
                        "event":"onPlayButton:",
                        "tag":"0",
                        "name":"播放录音"
                    }
                }
            }
        }
    }
    

    CoreData数据库操作

    1.建立CoreDataModel对象



    image.png

    2.根据统计类型查询数据库更新数据库

    #import "JH_AnalyseDataHelper.h"
    #define kManagedObjectContext [JH_ChatMessageManager sharedInstance].managedObjectContext
    #define JH_EventAnalyseData @"EventAnalyseData"
    #define JH_ViewControllerAnalyseData @"ViewControllerAnalyseData"
    
    @implementation JH_AnalyseDataHelper
    +(void)_AnalyseWithData:(NSDictionary *)data withType:(AnalyseType )analyseType{
        if (analyseType==AnalyseTypeViewController) {
            [self analyseVCWithData:data];
        }else if (analyseType == AnalyseTypeEvent){
            [self analyseEventWithData:data];
        }
        
        
    }
    /**
     分析统计页面
     */
    +(void)analyseVCWithData:(NSDictionary *)data{
        //判断是新建还是更新
        NSArray *list = [self _searchViewControllerData];
        //创建对应的类
        NSString *vcName = data[@"viewControllerName"];
        
        for (ViewControllerAnalyseData *vcModel in list) {
            if ([vcModel.viewControllerName isEqualToString:vcName]) {
                //更新时长数据
                vcModel.viewControllerTime = vcModel.viewControllerTime + [data[@"viewControllerTime"] floatValue];
                [[JH_ChatMessageManager sharedInstance] saveContext]; //保存
                return;
            }
        }
        //创建一个新的
        ViewControllerAnalyseData *vcModel = [NSEntityDescription insertNewObjectForEntityForName:JH_ViewControllerAnalyseData inManagedObjectContext:kManagedObjectContext];
        for (NSString *str in [data allKeys]) {
            if ([str isEqualToString:@"viewControllerTime"]) {
                float time = [data[str] floatValue];
                [vcModel setValue:@(time) forKey:str];
                continue;
            }
            [vcModel setValue:data[str] forKey:str];
        }
        
        [[JH_ChatMessageManager sharedInstance] saveContext]; //保存
    }
    /**
     分析统计事件
     */
    +(void)analyseEventWithData:(NSDictionary *)data{
        //判断是新建还是更新
        NSArray *list = [self _searchEventData];
        //创建对应的类
        NSString *eventName = data[@"eventName"];
        
        for (EventAnalyseData *vcModel in list) {
            if ([vcModel.eventName isEqualToString:eventName]) {
                //更新点击次数数据
                vcModel.eventCount = vcModel.eventCount + [data[@"eventCount"] integerValue];
                [[JH_ChatMessageManager sharedInstance] saveContext]; //保存
                return;
            }
        }
        
        //创建一个新的
        EventAnalyseData *eventModel = [NSEntityDescription insertNewObjectForEntityForName:JH_EventAnalyseData inManagedObjectContext:kManagedObjectContext];
        
        for (NSString *str in [data allKeys]) {
            if ([str isEqualToString:@"eventCount"]) {
                NSInteger count = [data[str] integerValue];
                [eventModel setValue:@(count) forKey:str];
                
                continue;
            }
            [eventModel setValue:data[str] forKey:str];
        }
        
        [[JH_ChatMessageManager sharedInstance] saveContext]; //保存
    }
    
    #pragma mark - 查询数据(暂时使用全部搜索)
    +(NSArray *)_searchViewControllerData{
        /**
         数据查询数据(全部)
         */
        NSFetchRequest *request = [[NSFetchRequest alloc] init];
        
        NSEntityDescription *entity = [NSEntityDescription entityForName:JH_ViewControllerAnalyseData
                                       
                                                  inManagedObjectContext:kManagedObjectContext];
        
        [request setEntity:entity];
        
        NSError *error = nil;
        
        NSArray *objectResults = [kManagedObjectContext
                                  
                                  executeFetchRequest:request
                                  
                                  error:&error];
        return objectResults;
        
    }
    +(NSArray *)_searchEventData{
        /**
         数据查询数据(全部)
         */
        NSFetchRequest *request = [[NSFetchRequest alloc] init];
        
        NSEntityDescription *entity = [NSEntityDescription entityForName:JH_EventAnalyseData
                                       
                                                  inManagedObjectContext:kManagedObjectContext];
        
        [request setEntity:entity];
        
        NSError *error = nil;
        
        NSArray *objectResults = [kManagedObjectContext
                                  
                                  executeFetchRequest:request
                                  
                                  error:&error];
        return objectResults;
        
    }
    

    相关文章

      网友评论

          本文标题:iOS无埋点数据统计实验

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