一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第23天,点击查看活动详情。
获取显示的文本
获取显示的文本,我们只需要针对特定的控件,调用相应的方法即可。我们以UIButton为例来介绍实现步骤。
首先声明一个UIView的分类UIView+TextContentData,然后在UIView的分类UIView+TextContentData添加 UIButton的分类
UIButton的分类。
UIView+TextContentData.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIView (TextContentData)
@property (nonatomic,copy,readonly) NSString *elementContent;
@end
@interface UIButton (TextContentData)
@end
NS_ASSUME_NONNULL_END
UIView+TextContentData.m
#import "UIView+TextContentData.h"
@implementation UIView (TextContentData)
- (NSString *)elementContent {
return nil;
}
@end
@implementation UIButton (TextContentData)
- (NSString *)elementContent {
return self.titleLabel.text;
}
@end
获取控件的文本埋点实现
+ (void)load {
[UIApplication sensorsdata_swizzleMethod:@selector(sendAction:to:from:forEvent:) withMethod:@selector(CountData_sendAction:to:from:forEvent:)];
}
- (BOOL)CountData_sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event {
UIView *view = (UIView *)sender;
NSMutableDictionary *prams = [[NSMutableDictionary alloc]init];
//获取控件类型
prams[@"$elementtype"] = view.elementType;
prams[@"element_content"] = view.elementContent;
[[SensorsAnalyticsSDK sharedInstance] track:@"$appclick" properties:prams];
return [self CountData_sendAction:action to:target from:sender forEvent:event];
}
我们这里只是以UIButton为例,如果想扩充其他控件,直接添加对应控件的分类。
获取控件所属页面
如何知道UIView属于那个UIViewController,这个就需要借助UIResponder了。
UIApplication、UIViewController、UIView类都是UIResponder的子类,在iOS应用程序中,UIApplication、 UIViewController、UIView类的对象也都是响应者,这些响应者会形成一个 响应者链。
一个完整的响应者链传递规则(顺序)大概如下: UIView→UIViewController→UIWindow→UIApplication→UIApplicationDelegate
如下图所示:
通过响应链图可知,对于任意一个视图来说,都能通过响应者链找到它所 在的视图控制器,也就是其所属的页面,从而达到获取所属页面信息的目 的。
注意:对于在iOS应用程序中实现了UIApplicationDelegate协议的类(通常为AppDelegate),如果它是继承自UIResponder,那么也会参与响应者 链的传递;如果不是继承自UIResponder(例如NSObject),那么不会参与响应者链的传递。
UIView+TextContentData.h
@interface UIView (TextContentData)
@property (nonatomic,copy,readonly) NSString *elementContent;
@property (nonatomic,strong,readonly) UIViewController *myViewController;
@end
UIView+TextContentData.m
#import "UIView+TextContentData.h"
@implementation UIView (TextContentData)
- (NSString *)elementContent {
return nil;
}
- (UIViewController *)myViewController {
UIResponder *responder = self;
while ((responder = [responder nextResponder])) {
if ([responder isKindOfClass:[UIViewController class]]) {
return (UIViewController *)responder;
}
}
return nil;
}
@end
获取控件所属页面埋点实现
+ (void)load {
[UIApplication sensorsdata_swizzleMethod:@selector(sendAction:to:from:forEvent:) withMethod:@selector(CountData_sendAction:to:from:forEvent:)];
}
- (BOOL)CountData_sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event {
UIView *view = (UIView *)sender;
NSMutableDictionary *prams = [[NSMutableDictionary alloc]init];
//获取控件类型
prams[@"$elementtype"] = view.elementType;
//获取控件的内容
prams[@"element_content"] = view.elementContent;
//获取所属的页面
UIViewController *vc = view.myViewController;
prams[@"element_screen"] = NSStringFromClass(vc.class);
[[SensorsAnalyticsSDK sharedInstance] track:@"$appclick" properties:prams];
return [self CountData_sendAction:action to:target from:sender forEvent:event];
}
更多控件
支持获取UISwitch控件文本信息
通过测试可以发现,UISwitch的$AppClick事件没有$element_content属性。针对这个问题,可以解释为UISwitch控件本身就没有显示任何文本。 为了方便分析,针对获取UISwitch控件的文本信息,我们可以定一个简单的规则:当UISwitch控件的on属性为YES时,文本为“checked”;当 UISwitch控件的on属性为NO时,文本为“unchecked”。
解决方案
声明 UISwitch的分类
@implementation UISwitch (TextContentData)
- (NSString *)elementContent {
return self.on ? @"checked":@"unchecked";
}
@end
滑动UISlider控件重复触发$AppClick事件解决方案
原因:
我们在滑动UISlider控件过程中,系统会依次触发 UITouchPhaseBegan、UITouchPhase-Moved、UITouchPhaseMoved、……、 UITouchPhaseEnded事件,而每一个事件都会触发UIApplication的- sendAction:to:from:forEvent:方法执行,从而触发$AppClick事件。
防止滑动UISlider重复响应,只有在UITouchPhaseEnded开始响应
//防止滑动UISlider控制
if(event.allTouches.anyObject.phase == UITouchPhaseEnded || [sender isKindOfClass:[UISwitch class]]) {
[[SensorsAnalyticsSDK sharedInstance] track:@"$appclick" properties:prams];
}