iOS手势全埋点

简介: iOS手势全埋点

前言

image.png

由于UIGestureRecognizer是一个抽象基类,所以它并不会处理具体的手势。因此,对于具体的手势触摸事件,需要使用相应的子类进行处理。

常见的具体手势识别器

UITapGestureRecognizer:轻拍手势

UILongPressGestureRecognizer:长按手势

UIPinchGestureRecognizer:捏合(缩放)手势

UIRotationGestureRecognizer:旋转手势

UISwipeGestureRecognizer:轻扫手势

UIPanGestureRecognizer:平移手势

UIScreenEdgePanGestureRecognizer:屏幕边缘平移手势

I、手势全埋点方案

接下来介绍如何实现手势识别的全埋点,来采集常见控件(UILabel、UIImageView)的轻拍和长按手势。

手势识别器使用了Target-Action设计模式,可调用UIView类中的-addGestureRecognizer:方法进行添加手势识别器

当我们为一个手势识别器添加一个或多个Target-Action后,在视图上进行触摸操作时,一旦系统识别了该手势,就会向所有的Target(对象)发送消息,并执行Action(方法)

主要是通过如下两个方法进行添加手势识别器

- initWithTarget:target action:
- addTarget:action:

addGestureRecognizer的使用例子

_tappedLabel.userInteractionEnabled = YES;
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
    [tap addTarget:self action:@selector(tapAction:)];
    [_tappedLabel addGestureRecognizer:tap];

虽然手势操作和UIControl类一样,均使用了Target-Action设计模式,但手势识别器并不会将消息交由UIApplication对象来发送。因此无法使用与UIControl控件相同的处理方式(通过响应者链的方式来实现全埋点)

为了采集控件的轻拍手势,我们可以通过Method Swizzling在UITapGestureRecognizer类中添加Target-Action的方法,添加一个新的Target-Action,并在新添加的Action中触发Click事件,进而实现控件轻拍手势全埋点。

1.1 轻拍手势全埋点

#import "UIGestureRecognizer+SensorsData.h"
#import "SensorsAnalyticsSDK.h"
#import "NSObject+SASwizzler.h"
@implementation UITapGestureRecognizer (SensorsData)
+ (void)load {
    // Swizzle initWithTarget:action: 方法
    [UITapGestureRecognizer sensorsdata_swizzleMethod:@selector(initWithTarget:action:) withMethod:@selector(sensorsdata_initWithTarget:action:)];
    // Swizzle addTarget:action: 方法
    [UITapGestureRecognizer sensorsdata_swizzleMethod:@selector(addTarget:action:) withMethod:@selector(sensorsdata_addTarget:action:)];
}
- (instancetype)sensorsdata_initWithTarget:(id)target action:(SEL)action {
    // 调用原始的初始化方法进行对象初始化
    [self sensorsdata_initWithTarget:target action:action];
    // 调用添加 Target-Action 方法,添加埋点的 Target-Action
    // 这里其实调用的是 sensorsdata_addTarget:action: 里的实现方法,因为已经进行了 swizzle
    [self addTarget:target action:action];
    return self;
}
- (void)sensorsdata_addTarget:(id)target action:(SEL)action {
    // 调用原始的方法,添加 Target-Action
    [self sensorsdata_addTarget:target action:action];
    // 新增 Target-Action,用于埋点
    [self sensorsdata_addTarget:self action:@selector(sensorsdata_trackTapGestureAction:)];
}
- (void)sensorsdata_trackTapGestureAction:(UITapGestureRecognizer *)sender {
    // 获取手势识别器的控件
    UIView *view = sender.view;
    // 暂只采集 UILabel 和 UIImageView
    BOOL isTrackClass = [view isKindOfClass:UILabel.class] || [view isKindOfClass:UIImageView.class];
    if (!isTrackClass) {
        return;
    }
    // Click事件的属性
    NSDictionary *properties = @{@"$element_type": NSStringFromClass(self.class)};
    // 触发Click 事件
    [[SensorsAnalyticsSDK sharedInstance] trackAppClickWithView:view properties:properties];
}
@end

1.2 长按手势全埋点

手势处于UIGestureRecognizerStateEnded状态时,才触发Click事件

@implementation UILongPressGestureRecognizer (SensorsData)
+ (void)load {
    // Swizzle initWithTarget:action: 方法
    [UILongPressGestureRecognizer sensorsdata_swizzleMethod:@selector(initWithTarget:action:) withMethod:@selector(sensorsdata_initWithTarget:action:)];
    // Swizzle addTarget:action: 方法
    [UILongPressGestureRecognizer sensorsdata_swizzleMethod:@selector(addTarget:action:) withMethod:@selector(sensorsdata_addTarget:action:)];
}
- (instancetype)sensorsdata_initWithTarget:(id)target action:(SEL)action {
    // 调用原始的初始化方法进行对象初始化
    [self sensorsdata_initWithTarget:target action:action];
    // 调用添加 Target-Action 方法,添加埋点的 Target-Action
    // 这里其实调用的是 sensorsdata_addTarget:action: 里的实现方法,因为已经进行了 swizzle
    [self addTarget:target action:action];
    return self;
}
- (void)sensorsdata_addTarget:(id)target action:(SEL)action {
    // 调用原始的方法,添加 Target-Action
    [self sensorsdata_addTarget:target action:action];
    // 新增 Target-Action,用于埋点
    [self sensorsdata_addTarget:self action:@selector(sensorsdata_trackLongPressGestureAction:)];
}
- (void)sensorsdata_trackLongPressGestureAction:(UILongPressGestureRecognizer *)sender {
    if (sender.state != UIGestureRecognizerStateEnded) {
        return;
    }
    // 获取手势识别器的控件
    UIView *view = sender.view;
    // 暂定只采集 UILabel 和 UIImageView
    BOOL isTrackClass = [view isKindOfClass:UILabel.class] || [view isKindOfClass:UIImageView.class];
    if (!isTrackClass) {
        return;
    }
    NSDictionary *properties = @{@"$element_type": NSStringFromClass(self.class)};
    // 触发Click 事件
    [[SensorsAnalyticsSDK sharedInstance] trackAppClickWithView:view properties:properties];
}
@end

II 、右划返回的事件与scrollView滚动事件冲突的解决方案

  • 通过 requireGestureRecognizerToFail方法来处理。

将两个手势依次处理, 一个校验失败,再执行另外一个手势的校验,以解决手势冲突.

[_bigScrollView.panGestureRecognizer requireGestureRecognizerToFail:self.navigationController.interactivePopGestureRecognizer];

see also

目录
相关文章
|
iOS开发
(六)IOS手势和触摸的用法
(六)IOS手势和触摸的用法
239 0
|
前端开发 数据可视化 安全
iOS 无痕埋点方案及实战分享
iOS 无痕埋点方案及实战分享
iOS 无痕埋点方案及实战分享
|
API iOS开发
iOS手势与变形
手势在用户交互中有着举足轻重的作用,这篇文字简单的介绍了iOS中的手势,并通过手势对控件进行变形处理。
119 0
|
iOS开发
如何使用iOS手势UIGestureRecognizer
如何使用iOS手势UIGestureRecognizer
115 0
|
数据安全/隐私保护 iOS开发
iOS 手势密码锁
首先看一下效果
134 0
|
监控 JavaScript Android开发
mPaas从埋点排查iOS离线包问题
随着mPaaS的用户量的不断加大,越来越多的客户使用到了框架的核心功能《离线包》, 官方文档给到的离线包的加载流程范围比较大,没那么细节,客户遇到离线包的问题时不知道如何去下手排查,所以需要更详细的加载流程协助客户排查问题。
696 0
mPaas从埋点排查iOS离线包问题
|
iOS开发
(七) IOS 响应者链和手势
(七) IOS 响应者链和手势
371 0
|
iOS开发
iOS开发中的手势体系——UIGestureRecognizer分析及其子类的使用(一)
iOS开发中的手势体系——UIGestureRecognizer分析及其子类的使用
245 0
iOS开发中的手势体系——UIGestureRecognizer分析及其子类的使用(一)
|
监控 JavaScript Android开发
排查指南 | 两个案例学会从埋点排查 iOS 离线包
首次打开离线包白屏以及报错“-1009”等该如何处理呢?
500 0
排查指南 | 两个案例学会从埋点排查 iOS 离线包
|
iOS开发
iOS开发中的手势体系——UIGestureRecognizer分析及其子类的使用(二)
iOS开发中的手势体系——UIGestureRecognizer分析及其子类的使用
373 0