iOS 实现UIButton自动化点击埋点

news/2025/3/5 9:49:53/

思路:我们HOOK UIControl的 addtarget:action:forControlEvents方法,交换UIControl的 addtarget:action:forControlEvents
方法的实现, 在交换的方法中添加原来响应的同时,再添加一个埋点响应,该响应方法实现了点击埋点操作,同时要添加一个标记为,记录我们添加过
点击埋点响应了,防止外部再次添加响应的时候,我们这里重复添加埋点响应,同时,还要hook removeTarget:action:forControlEvents方法,在该方法中记录我们绑定的点击处理次数,当次数大于0时,进行埋点上报

一下是我们的实现代码

static const void *lbmonitorActionNameKey = "monitorActionNameKey";
static const void *lbSenderAction = "lbSenderAction";
static const void *lbTabButtonId = "lbTabButtonId";
static const void *lbClickActionCounts = "lbClickActionCounts";@implementation UIControl (LB)
@dynamic actionName;+ (void)load
{lbinstanceMethod_fastExchangeImplementations([self class], @selector(addTarget:action:forControlEvents:), [self class], @selector(lbtracker_addCagegoryTarget:action:forControlEvents:));instanceMethod_fastExchangeImplementations([self class], @selector(removeTarget:action:forControlEvents:), [self class], @selector(lbtracker_removeCagegoryTarget:action:forControlEvents:));
}- (void)lbtracker_addCagegoryTarget:(id)targetaction:(SEL)actionforControlEvents:(UIControlEvents)controlEvents
{// 自动化埋点:只针对”点击“进行埋点,一次点击一次上报,且先埋点后业务。if ([self isKindOfClass:[UITextField class]] == NO && controlEvents == UIControlEventTouchUpInside) {// 避免:业务添加多次点击回调时,触发多次埋点或者点击处理顺序错乱。NSNumber *hookClickMethod = objc_getAssociatedObject(self, "lb_track_click");NSLog(@"哈哈哈哈哈这里的hookClickMethod%@ %@", self, hookClickMethod);if (!hookClickMethod) {objc_setAssociatedObject(self, "lb_track_click", @(1), OBJC_ASSOCIATION_RETAIN);[self setSenderAction:NSStringFromSelector(action)];[self autotracker_addCagegoryTarget:selfaction:@selector(autotracker_monitorAction:forEvent:)forControlEvents:controlEvents];}// 记录控件绑定点击处理次数,当次数大于0时,进行点击埋点上报。NSArray *actionNames = [self actionsForTarget:target forControlEvent:controlEvents];NSLog(@"哈哈哈哈哈这里这里的数量数量%@ %@", actionNames, NSStringFromSelector(action));if (actionNames.count == 0 || ![actionNames containsObject:NSStringFromSelector(action)]) {NSLog(@"这里的原始数量%ld %@", [self lbtracker_clickActionCounts], self);[self setAutotracker_clickActionCounts:[self autotracker_clickActionCounts] + 1];}}[self autotracker_addCagegoryTarget:targetaction:actionforControlEvents:controlEvents];
}- (void)lbtracker_removeCagegoryTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
{// 减少控件绑定点击处理次数,当次数大于0时,进行点击埋点上报。NSArray *actionNames = [self actionsForTarget:target forControlEvent:controlEvents];if (actionNames.count > 0 && [actionNames containsObject:NSStringFromSelector(action)]) {APLogInfo(@"AutoTrack", @"Click %@ remove T", NSStringFromSelector(action));[self setlbTracker_clickActionCounts:[self lbtracker_clickActionCounts] - 1];}[self lbtracker_removeCagegoryTarget:target action:action forControlEvents:controlEvents];
}- (void)lbtracker_monitorAction:(UIControl *)sender forEvent:(UIEvent *)event
{LBLog(@"lbTrack", @"Click %@ counts = %@", self.senderAction, @([self lbtracker_clickActionCounts]));if (self.skipTrack || 0 == [self lbtracker_clickActionCounts]) {return;}[self lbtracker_parseClickPoint:event];//执行埋点操作
}- (NSString *)actionName {return objc_getAssociatedObject(self, monitorActionNameKey);
}- (void)setActionName:(NSString *)monitorActionName{objc_setAssociatedObject(self, monitorActionNameKey,monitorActionName,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}- (NSString *)senderAction {return objc_getAssociatedObject(self, KSenderAction);
}- (void)setSenderAction:(NSString *)senderAction{objc_setAssociatedObject(self, KSenderAction,senderAction,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}- (NSString *)tabButtonId {return objc_getAssociatedObject(self, KTabButtonId);
}- (void)setTabButtonId:(NSString *)tabButtonId {objc_setAssociatedObject(self, KTabButtonId, tabButtonId, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}- (NSInteger)autotracker_clickActionCounts
{NSNumber *counts = objc_getAssociatedObject(self, LBClickActionCounts);return [counts integerValue];
}- (void)setLBtracker_clickActionCounts:(NSInteger)count
{NSLog(@"这里的数量这里的数量%ld", count);objc_setAssociatedObject(self, LBClickActionCounts, @(count), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}- (void)lbtracker_parseClickPoint:(UIEvent *)event
{// 获取点击位置坐标CGPoint clickPoint;UITouch *touch = [event touchesForView:self].anyObject;if (touch) {clickPoint = [touch locationInView:self];}if ([self respondsToSelector:@selector(lbLogModel_auk)]) {LBLogModel *model = [self performSelector:@selector(lbLogModel_auk)];model.clickPoint = clickPoint;}
}

http://www.ppmy.cn/news/1576784.html

相关文章

多镜头视频生成、机器人抓取、扩散模型个性化 | Big Model weekly第58期

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入! 01 GLM-4-Voice: Towards Intelligent and Human-Like End-to-End Spoken Chatbot 本文介绍了一种名为GLM-4-Voice的智能且类人化的端到端语音聊天机器人。它支持中文和英文,能够进行实时语音对话&a…

字节跳动发布 Trae AI IDE!支持 DeepSeek R1 V3,AI 编程新时代来了!

3 月 3 日,字节跳动重磅发布国内首款 AI 原生集成开发环境(AI IDE)——Trae 国内版! Trae 不只是一个传统的 IDE,它深度融合 AI,搭载 doubao-1.5-pro 大模型,同时支持DeepSeek R1 & V3&…

Wpf-ReactiveUI-Usercontrol交互

文章目录 1、使用属性绑定UserControl 部分(MyUserControl.xaml.cs)UserControl 视图模型部分(MyUserControlViewModel.cs)主界面部分(MainWindow.xaml)主界面视图模型部分(MainWindowViewModel.cs)2、使用消息传递UserControl 视图模型部分(MyUserControlViewModel.c…

Linux Sed实战指南:从入门到精通

一、Sed核心概念与优势 Sed(Stream Editor) 是一种非交互式的流式文本编辑器,通过逐行处理实现自动化文本操作。其核心优势包括: 无需打开文件:直接通过命令行操作文本流,适用于脚本自动化高效处理大文件:仅将当前处理行加载到内存,资源消耗低支持正则表达式:实现复杂…

Tauri跨端笔记实战(4) - 如何实现系统级截图

前言 Tauri 跨端笔记实战项目是基于 Notegen 开源项目,本系列深度解析如何运用Tauri框架开发跨平台AI笔记应用。涵盖核心技术选型、架构设计、典型场景开发及常见问题解决方案,通过代码级演示带您掌握集成AI能力的全流程开发技巧。 你可以通过本系列教…

Java-实现PDF合同模板填写内容并导出PDF文件

可用于公司用户合同导出pdf文件 效果图 一、导入所需要jar包 <!--生成PDF--><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.11</version></dependency><dependency&…

RK3568平台(GPIO篇)libgpiod的使用

libgpiod 是一个用于与 Linux GPIO 子系统交互的用户空间库。它提供了一组简单的 API,允许开发者通过用户空间程序控制 GPIO 引脚,而无需编写内核模块。libgpiod 是替代旧的 sysfs GPIO 接口的推荐方式。 一.libgpiod 的基本概念 Chip:GPIO 控制器,通常对应 /dev/gpiochip…

Spring Cloud Alibaba学习 4- Spring Cloud Gateway入门使用

Spring Cloud Alibaba学习 4- Spring Cloud Gateway入门使用 中文文档Spring Cloud Gateway 中文文档 一. 基本使用 1. Predicate配置 1.1 配置参数介绍 直接通过官方给的application.yml介绍&#xff0c;这里就不介绍简写方式了&#xff0c;直接介绍完整方式 spring:clo…