• 第47月第21天 iOS 无痕埋点解决方案


    1.

    生成 Target-Action 埋点的唯一 ID

    Target-Action 是手势和 UIControl 的回调,一般使用如下代码

    1. -[UIControl addTarget:action:events:]
    2. -[UIGestureRecognizer initWithTarget:action:]

    我们 hook 了 -[UIControl addTarget:action:events:] 方法,创建了一个 Action 对象作为附属对象,和实际的 target 一同添加到 UIControl 中。当 UIControl 触发了事件,就会同时向业务对象和 Action 对象发送消息,从而产生埋点。故我们可以在 -[UIControl addTarget:action:events:] 方法中获取到 target、action、event。还能从 -[Action action:] 方法中获取实时埋点数据。

    采集

    -[UIControl addTarget:action:events:]

    在此方法中,我们可以获取到 UIControl 类名,target 对象,action 方法名,events 事件名。由于后三个数据在下面的方法中无法获取,所以会记录后三个数据到 Action 对象中,供 Action 对象在触发下面的方法时获取对应数据:

    //  In UIControl+Hook.m
    
    - (void)hook_addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)events {
    
        // Call origin method
        [self hook_addTarget:target action:action forControlEvents:events];
        
        //  Create Action object
        MyTargetAction *action = [[MyTargetAction alloc] init];
        action.targetName = NSStringFromClass([target class]);
        action.action = NSStringFromSelector(action);
        action.events = events;
    
        // Add Action object
        [self hook_addTarget:action action:@selector(action:) forControlEvents:events];
    }
    
    

    -[Action action:]

    此方法是实际埋点执行的方法,由于此方法只能获取 self(Action 对象)和 sender(UIControl 对象),故实际埋点数据还是依赖前一个方法临时保存的数据。

    此时我们可以在方法中构成埋点数据。

    • self(Action 对象)
    • sender(UIControl 对象)
      • VC(可以根据 UIControl 获取所在 VC)
    • self.targetName(target 类名)
    • self.action(action 方法名)
    • self.events(events 值)

    拼接事件

    Action 对象

    此对象是 SDK 内部对象,无任何信息

    sender

    控件对象,大部分按钮不会继承,所以也不会有信息。

    self.targetName

    响应者类名,此类一般为 VC 的类名,或者某个 View 的类名,故此信息可用于拼接。

    self.action

    响应方法名,于前一个相同,但不同事件一般会有不同方法回调,所以方法名也可以作为唯一事件 ID。

    self.events

    事件类型,不同控件不同事件,但按钮基本为 UIControlEventsTouchUpInside,如果要区分不同控件则可以加入,本文只考虑按钮情况。故不加入此信息

    最终事件 ID 如下:

    VCClassName#TargetClassName#ActionName

    //  In MyTargetAction.m
    
    - (void)action:(UIControl *)sender {
        NSString *event_code = ({
            NSString *viewController = ({
                UIResponder *responder = sender;
                while (responder) {
                    responder = responder.nextResponder;
                    if ([responder isKindOfClass:[UIViewController class]]) {
                        break;
                    } else if ([responder isKindeOfClass:[UIWindow class]]) {
                        break;
                    }
                }
                NSStringFromClass([responder class]);
            });
            [NSString stringWithFormat:@"%@#%@#%@", viewController, self.targetName, self.actionName];
        });
            
        [Tracker trackEvent:event_code];
    }
    

    举例:

    UIViewController#UIViewController#onClick:

    UIViewController#MenuItemCell#onClickAdd:




    https://www.jianshu.com/p/f3d5e7beca23

  • 相关阅读:
    跨域资源共享 CORS 详解
    Vue.js 与 Laravel 分离
    Laravel 5.4+Vue.js 初体验:Laravel下配置运行Vue.js
    移动端web及app设计尺寸
    另辟蹊径:vue单页面,多路由,前进刷新,后退不刷新
    vue2.0 keep-alive最佳实践
    教你用Cordova打包Vue项目
    oracle_数据处理
    oracle_集合函数
    oaracel 函数_行转列
  • 原文地址:https://www.cnblogs.com/javastart/p/13542272.html
Copyright © 2020-2023  润新知