一起养成写作习惯!这是我参与「日新计划 4 月更文挑战」的第25天,点击查看活动详情。

支持更多控件

支持UISwitch、UISegmentedControl、UIStepper控件

这些控件都不响应UIControlEventTouchDown类型的Action,也就是说,没有触发-sensorsdata_touchDownAction:event:办法,因而,也就不会触发$AppClick事情。实际上,这些控件增加的是 UIControlEventValueChanged类型的Action

+ (void)load {
    [UIControl sensorsdata_swizzleMethod:@selector(didMoveToSuperview) withMethod:@selector(CountData_didMoveToSuperview)];
}
- (void)CountData_didMoveToSuperview {
    //调用前交换原始办法
    [self CountData_didMoveToSuperview];
    //判别是否为一些特殊的控件
    if([self isKindOfClass:[UISwitch class]] ||
       [self isKindOfClass:[UISegmentedControl class]] ||
       [self isKindOfClass:[UIStepper class]] 
     ) {
        [self addTarget:self action:@selector(countData_valueChangedAction:event:) forControlEvents:UIControlEventValueChanged];
    }else {
        [self addTarget:self action:@selector(CountData_touchDownAction:withEvent:) forControlEvents:UIControlEventTouchDown];
    }
}
-(void)countData_valueChangedAction:(UIControl *)sender event:(UIEvent *)event {
    if ([self CountData_isAddMultipleTargetActionsWithDefaultEvent:UIControlEventValueChanged]) {    
        [[SensorsAnalyticsSDK sharedInstance]track:@"appclick" properties:nil];
    }
}
-(BOOL)CountData_isAddMultipleTargetActionsWithDefaultEvent:(UIControlEvents)defaultEvent {
    ///假如有多个target,阐明除了增加的target,还有其他
    ///那么回来YES,触发$AppClick事情
    if (self.allTargets.count > 2) {
        return YES;
    }
    //假如控件本身为target,而且增加了不是UIControlEventTouchDown类型的Action
    //阐明开发者以控件本身为target,而且已增加增加Action
    //那么回来YES,触发$AppClick事情
    if((self.allControlEvents & UIControlEventAllEvents) != UIControlEventTouchDown) {
        return YES;
    }
    //假如控件本身为Target,而且增加了两个以上的UIControlEventTouchDown类型的Action
    //阐明开发者自行增加了Action
    //那么回来YES,触发$AppClick事情
    if([self actionsForTarget:self forControlEvent:defaultEvent].count > 2) {
        return YES;
    }
    return NO;
}

支持UISlider控件

UISlider增加的是UIControlEventTouchDown 类型的Action,这会导致在只点击而没有滑动UISlider时,也会触发 $AppClick事情,咱们更希望只要手停止滑动UISlider时,才触发$AppClick事情。因而,需求修正UIControl+SensorsData.m文件中的- sensorsdata_didMoveToSuperview办法,默许也给UISlider增加UIControlEventValueChanged类型的Action

- (void)CountData_didMoveToSuperview {
    //调用前交换原始办法
    [self CountData_didMoveToSuperview];
    //判别是否为一些特殊的控件
    if([self isKindOfClass:[UISwitch class]] ||
       [self isKindOfClass:[UISegmentedControl class]] ||
       [self isKindOfClass:[UIStepper class]] ||
       [self isKindOfClass:[UISlider class]]) {
        [self addTarget:self action:@selector(countData_valueChangedAction:event:) forControlEvents:UIControlEventValueChanged];
    }else {
        [self addTarget:self action:@selector(CountData_touchDownAction:withEvent:) forControlEvents:UIControlEventTouchDown];
    }
}

在滑动UISlider过程中,会一直触发$AppClick事情。因而,咱们还需求修正UIControl+CountData.m文件中 的-CountData_valueChanged Action:event:办法,确保假如是UISlider控件, 只要在手抬起的时分才触发$AppClick事情。

-(void)countData_valueChangedAction:(UIControl *)sender event:(UIEvent *)event {
    if ([sender isKindOfClass:UISlider.class] && event.allTouches.anyObject.phase != UITouchPhaseEnded) {
        return;
    }
    if ([self CountData_isAddMultipleTargetActionsWithDefaultEvent:UIControlEventValueChanged]) {  
        [[SensorsAnalyticsSDK sharedInstance]track:@"appclick" properties:nil];
    }
}

这样处理之后,当咱们滑动UISlider时,只会在手抬起时触发 $AppClick事情。

计划总结

计划一和计划二其实都运用了iOS中的Target- Action形式,这两种计划各有好坏。

  • 关于计划一:假如给一个控件增加了多个 Target-Action,会导致多次触发$AppClick事情。
  • 关于计划二:因为SDK为控件增加了一个默许触发类型的Action,因而,假如开发者在开发 过程中使用UIControl类的allTargets或者 allControlEvents特点进行逻辑判别,有可能会引进一些无法意料的问题。 因而,在挑选计划的时分,读者可以根据自 己的实际情况和需求,来确定终究的实现计划。