ios 无码统计埋点
ios无码统计埋点总结 一
第一种方式就是业务代码与统计代码相分离,利用runTime的特性,具体操作如下
定义工具类
@interface WHookUtility : NSObject
+ (void)swizzlingInClass:(Class)cls originalSelector:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector;
@end
#import <objc/runtime.h>
+ (void)swizzlingInClass:(Class)cls originalSelector:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector
{
Class class = cls;
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
对于以上的函数需要有以下说明:
1 上面的函数主要作用就是交换两个方法的实现,主要的三句代码是:
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
让我举个栗子��:比如你需要统计一个viewController的生命周期开始和结束,那一搬情况下是不是需要在它的
viewWillAppear viewDidDisappear里面写上一句监听的代码[UMXXXX trackEvent:@"EventName"]
如果在每个页面里面都这样写,那么统计这一块的代码耦合很高,这样很不好。现在有一个解决方法,利用RunTime特性Hook住
viewWillAppear viewDidDisappear 这两个函数。具体实现原理看以下UIViewController+userStatics.h
的demo。
2 除了函数的主要作用的三句代码那class_addMethod class_replaceMethod 的作用是什么呢
假如你hook的函数并不存在比如随意一个函数viewWillShow 那么这两句代码就稍微有点有作用了,至少你在你hook的
那个类里面执行[self performSelector:@selector(viewWillShow) withObject:nil]不会崩溃。
(前提是你已经定义好了交换的函数哦)。总的来说只要你不莫名其妙的写出hook不存在的函数,这两个函数是没用的。
即使hook了不存在的函数也不会崩溃的。如果你发现这两句代码还有其它的作用,可以交流一下~
现在我们来使用一下以上的类
建一个基于UIViewController的类别
#import "UIViewController+userStatics.h"
#import "WHookUtility.h"
@implementation UIViewController (userStatics)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL originalSelector = @selector(viewWillAppear:);
SEL swizzledSelector = @selector(swiz_viewWillAppear:);
[WHookUtility swizzlingInClass:[self class] originalSelector:originalSelector swizzledSelector:swizzledSelector];
SEL originalSelectorDis = @selector(viewWillDisappear:);
SEL swizzledSelectorDis = @selector(swiz_viewWillDisappear:);
[WHookUtility swizzlingInClass:[self class] originalSelector:originalSelectorDis swizzledSelector:swizzledSelectorDis];
});
}
#pragma mark - Method Swizzling
swiz_viewWillAppear:(BOOL)animated swiz_viewWillDisappear:(BOOL)animated 是我自己在类别里面定义的函数,
在以上的load函数里面我将它们与 viewWillAppear: viewWillDisappear: 交换了。所以当一个类里面执行viewWillAppear:
它事实上执行的是函数swiz_viewWillAppear:(BOOL)animated 你会发现在函数swiz_viewWillAppear:(BOOL)animated
里面有句代码 [self swiz_viewWillAppear:animated]; 由于交换的原因它事实上执行的是函数viewWillAppear:。
- (void)swiz_viewWillAppear:(BOOL)animated
{
//插入需要执行的代码
NSLog(@"我在viewWillAppear执行前偷偷插入了一段代码%@",[self class]);
//不能干扰原来的代码流程,插入代码结束后要让本来该执行的代码继续执行
[self swiz_viewWillAppear:animated];
}
- (void)swiz_viewWillDisappear:(BOOL)animated
{
//插入需要执行的代码
NSString *pageName=NSStringFromClass([self class]);
NSLog(@"结束监听%@",pageName);
//不能干扰原来的代码流程,插入代码结束后要让本来该执行的代码继续执行
[self swiz_viewWillDisappear:animated];
}
这种runTime方法也可以用在其它的类比如监听整个app的按钮点击:
#import "UIControl+userStatics.h"
#import "WHookUtility.h"
@implementation UIControl (userStatics)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL originalSelector = @selector(sendAction:to:forEvent:);
SEL swizzledSelector = @selector(swiz_sendAction:to:forEvent:);
[WHookUtility swizzlingInClass:[self class] originalSelector:originalSelector swizzledSelector:swizzledSelector];
});
}
#pragma mark - Method Swizzling
- (void)swiz_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event;
{
//插入埋点代码
[self performUserStastisticsAction:action to:target forEvent:event];
[self swiz_sendAction:action to:target forEvent:event];
}
- (void)performUserStastisticsAction:(SEL)action to:(id)target forEvent:(UIEvent *)event;
{
NSLog(@"\n***hook success.\n[1]action:%@\n[2]target:%@ \n[3]event:%ld", NSStringFromSelector(action), target, (long)event);
}
但是这种方法有一个突出的问题解决不了:无法交换代理函数
你如果想要监听webview的代理函数,tableView的代理函数那就无法用这种方法了。
ios 无码统计埋点相关推荐
- Cobub无码埋点关键技术的实现
随着大数据时代的到来,数据采集也已经变的越来越重要.前端埋点作为一个比较成熟的数据接入手段被广泛应用着.目前埋点分为两种方式,有码与无码埋点.有码埋点比较容易理解,即调用SDK的API,在代码中插入埋 ...
- 【无码专区7】括号序列(思维)
因为只有std,没有自我实现,所以是无码专区 主要是为了训练思维能力 solution才是dls正解,但是因为只有潦草几句,所以大部分会有我自己基于正解上面的算法实现过程,可能选择的算法跟std中dl ...
- 【无码专区2】序列划分(数学)
有std,但是没有自我实现,所以是无码专区 description 完全由数字组成的字符串 sss,划分成若干段,每一段看成一个十进制的数(允许前导零)求有多少种划分方法使得相邻两个数至少一个是 DD ...
- php淘金农场源码,2018Thinkphp仿淘金农场开源源码统H5农场复利源码带商城仓库商店...
演示地址:如有演示站请以演示为准,无演示站以截图为准,源码太多服务器有限,无法搭建所有源码演示站,请谅解! 新手购买指导:1.在本站注册账号 丨 2.登录已注册账号充值源码所需金币 丨 3.登录账号下 ...
- 华为 A199 / Ascend G710摄像头拍摄样张 多图 高清无码 慎入
前方高能反应,华为 A199 / Ascend G710摄像头拍摄样张,多图.高清.无码! 废话少说,直接来个连拍的,发现华为A199的连拍速度还不错,不过连拍的张数比较少 今天的天气灰蒙蒙的,但 ...
- 心中无码,自然高清 | 联合去马赛克与超分辨率研究论文Pytorch复现
作者 | 知凡,个人公众号:林木蔚然读书会(ID:EspressoOcean),知乎ID:Uno Whoiam 本文授权转载自知乎 本文结构 简单扫盲 什么是去马赛克 什么是超分辨率 <Deep ...
- 开源ImageFilter库For IOS源码发布
开源ImageFilter库For IOS源码发布 鉴于之前有朋友反映将ImageFilterForC直接用于XCODE开发会报出错误的原因.最近正好入手一部MAC PRO,所以顺便将I ...
- 【无码专区13】最小公倍数(线段树)
因为只有std,没有自我实现,所以是无码专区 主要是为了训练思维能力 my idea顾名思义,记录了我的整个思维过程,以及自己部分实现细节口胡,还有期望分数 solution才是dls正解,但是因为只 ...
- 【无码专区12】子集和(背包dp)
此题已自我实现,但仍归于无码专区 本题在考场上就过了,所以难度并不高,发现性质即可. problem 有 nnn 个正整数 a1,a2,...,ana_1,a_2,...,a_na1,a2,... ...
最新文章
- Intel SGX Remote Attestation实例代码安装和执行,笔记
- ActiveMQ入门系列二:入门代码实例(点对点模式)
- 1.6 Java字节流的使用:字节输入/输出流、文件输入/输出流、字节数组输入/输出流
- 前端学习(2853):简单秒杀系统学习之页面事件
- 机器视觉:锡膏印刷质量3D检测光学系统
- JavaScript、canvas小球加速和减速运动
- python多叉树_python中高效的四叉树实现
- 2007 word打开无响应
- 阿里云云开发平台的创建与部署
- java 数据库密码加密解密方法
- 万里长城第一里——实习之后台开发
- 「小猪佩奇」:成功儿童IP背后的商业逻辑和方法论
- Failed to resolve org.junit.vintage:junit-vintage-engine:5.6.2
- Opencv+Python学习记录9:掩膜(掩码)的使用(内附详细代码)
- 简单易懂的小学除法思维导图
- 鲸落送书第二期清华出版社系列丛书
- 几款微博同步工具比较
- 2021年R2移动式压力容器充装复审考试及R2移动式压力容器充装证考试
- Fama-French 三因子模型在A股市场的实证研究
- 蓝牙4.0android开发,Android蓝牙4.0开发