(3)实时分析示意图,而无码埋点

最近在负责公司的HubbleData的埋点SDK的开发任务,有码埋点比较容易理解

0 引言

近期在担负集团的HubbleData的埋点SDK的付出职务,产品的雏形其实在几年前就已经有了,公司里面的例如考拉、易信、LOFTE奥迪Q5、美学、漫画等多款产品都已接入使用。

下图给出哈勃勒Data SDK有个别应用的有的分析的来得页面:

(1)大概浏览示意图

事件

(2)事件分析示意图

事件

(3)实时分析示意图

事件

其余哈勃勒Data平台还持有留存分析、漏斗分析、粘性分析、数据看板等各种意义,方便有关总管士对成品用户作为举行更进一步的探索分析。

老版本的SDK的筹划是代码埋点完结的,就算对于有个别比较成熟的出品,代码埋点完全能够达标产品方的要求,可是对于部分新开发银行可能需频仍转移的急需的新产品等,考虑到其爱戴的资本大,代价高等缺点,哈勃勒Data无埋点SDK的布署就突显尤其首要了。

自己根本担负iOS端无埋点以及可视化圈选的办事,作品主要系统讲授一下HubbleData无埋点SDK在iOS端的设计与贯彻和部分有关难点的缓解,后续将针对全数埋点的贯彻流程与可视化圈选等情节再作分享。

① 、埋点简介

By Cobub OP
Team
 in 博客未分类

1.1 二种埋点的兑现格局简介

埋点的艺术分为三类:代码埋点、可视化埋点和无埋点。那里大约的牵线一下二种埋点方式:

(1)
代码埋点就是在代码的关键部位植入所要收集数据的N行代码,必要挖开产品笔者,深入摸底产品的政工逻辑及项目组织,上面代码模拟展现的就是点击提交订单的时候哈勃勒Data
SDK代码埋点;

代码埋点示例

(2)
可视化埋点即用可视化交互的主意圈选出所要采集数据的控件,当用户作为发出时,即可收集到相应的埋点数据。相比较于前方的代码埋点而言,可视化埋点能够化解代码埋点代价大花费高的标题,不过力不从心灵活的自定义埋点属性。

可视化埋点流程

(3)
无埋点也叫全埋点,即不需求用户积极埋点,能够收集用户拥有的操作行为,同样采用可视化圈选,用户能够获得所想采集的埋点数据,能够消除可视化圈选中多少不可回溯的题目。下图给出了无埋点数据收集的简约流程。

无埋点数据搜集流程

哈勃勒Data
SDK的统筹重点是代码埋点结合无埋点的多少搜集格局,个中也事关到可视化埋点中的显示屏类别化及事件绑定机制,本文主要介绍一下无埋点的安顿与完毕。

11
hours ago  0  59

1.2 无埋点SDK设计详细流程

下图给出哈勃勒Data无埋点SDK在iOS端的设计完结:

无埋点详细布署流程

从上海教室能够看来,哈勃勒Data的无埋点是在代码埋点的底子上落实的,所处无埋点的难处也就集中在偏下四个地方:

(1)自动获取埋点的EventID
(2)自动获取埋点的时机
(3)自动获取埋点需采集的属性

正文重要就那多少个地方展开剖析,第三局地关键讲一下轩然大波唯一ID的分明,第贰片段重视讲一下无埋点的搜集的实现,首要是各个风云产生采集的机会以及待采集的习性的配备。

哈勃勒Data
SDK还提到到无数别样效用,包括显示器体系可视化、代码埋点、精准渠道追踪等,那里不再介绍,后边会陆续分享有关的技能实现。

乘机大数目时期的到来,数据搜集也早已变的特别重要。前端埋点作为2个比较早熟的多少连接手段被广泛应用着。如今埋点分为二种方法,有码与无码埋点。有码埋点相比较便于精通,即调用SDK的API,在代码中插入埋点的有关代码,完毕用户作为采集。由于大家在开发项目标时候,埋点都是手动的,每趟业务须要的转移都要随地埋点,而无码埋点,即不供给手动插入代码,只须求中期开始展览连锁安顿,SDK自动收集用户作为,极大程度制止了因供给变动、埋点错误等原因造成的再度埋点繁复工作。本文首要介绍无码埋点的技艺达成。

二 、事件唯一ID的规定

为了落实在可视化圈选的时的事件的唯一性,每3个无埋点的风云采访都不可能不有且仅有四个唯一的标识符来区分区其他事件。分化于代码埋点,用户能够自定义的布局本人所需的伊芙ntID,无埋点进程中,须要SDK自个儿陈设每1个搜集事件的伊芙ntID,通过可视化圈选的操作,筛选出相应的伊夫ntID所对应的数量音信。哈勃勒Data采纳的是布局view唯一标识字符串的点子去唯一的标识那样的一个事件,首要由view的层级结构path路径、该view的到处页面类名以及view所带的有的自笔者定位属性等整合,并由此SHA256编码来博取唯一的伊夫ntID。

上边将完整系统介绍一些事变唯一ID的扭转进度。

无码埋点的落到实处流程

图片 1
1.可视化视图圈选,在页面上会出现转移的圆形,拖动圆圈至想安顿事件的控件上,将会弹出输入事件的弹框。
2.在上一步的弹框中输入自定义的事件名称,名称将会和视图的viewPath绑定起来。view帕特h是视图的唯一标识,在下文中将详细讲解。
3.用户点击了控件,判断控件是不是绑定过事件,如绑定则实行事件上传。

2.1 控件的层级结构path构造

贯彻流程中的技术点

2.1.1 普通view的层级结构path构造

层级结构path首固然基于页面包车型客车控件树构造而成,每个view都有superview与subviews的习性,将每一个view的superview作为树的父节点,将其subviews作为子节点,那样就能把全路app上的富有view组成一棵高大的控件树,个中树的顶层是UIWindow,然后是每2个view节点依次向下展开。下图给出2个归纳的控件树的结构图。

空中树结构

上边会详细介绍一下HubbleData的绝无仅有标识路径的布局形式。

不同类

同类

像上海教室1所示,倘使二个view的subviews中都以见仁见智品类的,比如像下图图1所示的控件树那样,能够唯一标识UILabel和UIButton控件为:

UIView_UILabel
UIView_UIButton

不过真正的页面是不会像赏心悦目中的全数控件都以例外体系的,能够说那种极其气象基本不存在,假诺照旧依据上述的办法来布局路径的话,八个UILabel都会被标识成UIView_UILabel,那明显不能够区分多个控件。由此唯有是各类控件节点的不二法门名称是心有余而力不足唯一标识这么些控件的,那里哈勃勒Data插足了此控件节点在父视图中的index。比如上海体育场面2,能够将五个UILabel标识为:

UIView(0)_UILabel(0)
UIView(0)_UILabel(1)

那里倘诺父视图是index为0的贰个节点,这样就足以完全的区分出四个控件了。

那么余下的难点正是每个UIView index索引值的规定。

各种UIView都有subviews属性,每1个子视图都有3个被addsubView的先后,其实要拿的那一个index正是子视图被add的次序,那么该怎么获得这么些顺序呢,在苹果的法定认证文书档案中,岁UIView的subviews属性,是那样介绍的:

@property(nonatomic, readonly, copy) NSArray *subviews

You can use this property to retrieve the subviews associated with your custom view hierarchies. 
The order of the subviews in the array reflects their visible order on the screen.

即每二个子视图在那个subviews数组中的索引就是哈勃勒Data要拿的index。

本着繁复的视图方式,如下图所示,依据上述的层级结构路径构造方法获得的绝无仅有层级路径为:

UIView(0)_UILabel(0)
UIView(0)_UIButton(1)
UIView(0)_UIButton(2)  

混合

从上述的解析可见,遵照上述介绍的办法举行view的绝无仅有层级路径标识,对大多数的页面来说已经足足,不过对于部分尤为灵活点的页面,由于部分政工须求等原因,开发职员平常会调用removeFromSuperview,
insertSubview:atIndex:, insertSubview:
belowSubview:等函数,都会小幅的影响全体页面包车型客车subviews的索引值,比如现在作者将上图所示的UILabel移动到八个UIButton的末端,那么得到的唯一层级路径为:

UIView(0)_UIButton(0)
UIView(0)_UIButton(1)
UIView(0)_UILabel(2)  

混合

可以发现,唯一层级路径已经被转移,然则任何页面却从没产生变化,不仅会时有发生新的事件(比如UIButton(0),UILabel(2)),连UIButton(1)事件的搜集也会出错,尽管是见仁见智的风云,却收获了分化的eventID,所以须要增强组织的层级结构路径的稳健型。

正像刚刚提到的,差异品类的UIView不需求做index的界别,那么在收获那些index的时候,不是简单的从subviews这几个数组中获取其对应的索引值,而是实行二个简单易行的同类归并再取索引值,3个一点也不细略的拍卖。

for (UIView *view in subviews) {
    if ([NSStringFromClass([subview class]) isEqualToString:NSStringFromClass(class)]) { //class为待筛选的类
        [array addObject:view];
    }
}

那样就能够获得array中的index作为其真正的索引值,获得的层级结构路径为:

UIView(0)_UILabel(0)
UIView(0)_UIButton(0)
UIView(0)_UIButton(1) 

那时候无论UIlabel的岗位位于什么地方,都不会转移那些路子的布局样式,大大扩充了稳健型。其实也能发现,那无非只好提升稳健型,并不可能从根本上解决这些难点,比要是本人把四个UIButton的各样交流了,大概去除了第3个,此时如故会取得部分不标准的层级路径。此题材会一而再消除,会逐步引入误差体积和相似度那一个定义,即假若在误差范围内,则会议及展览开更为的十分,具体的缓解方案本篇不在介绍。

可视化视图圈选达成

自定义UIWindow的子类,当做悬浮小圆圈,添加UIPanGestureRecognizer手势,依照手势的移位,设置悬浮框的移动。手势甘休时取得悬浮窗大旨点的坐标。
遍历主window上的子视图,找到包括上述悬浮窗主题点且能响应用户交互的最里层视图,即为用户能够圈选的视图。
参照iOS控件的音讯传递链,有个为主措施。UIView hitTest:(CGPoint)point
with伊芙nt:(UI伊芙nt
*)event。此API自动遍历子视图,找到包含point的视图,event传nil。由于event参数是nil,最后找到的视图并不一定是能响应用户手势的视图,如若不可能响应则遍历其父视图,直到找到能响应用户作为的视图。

2.1.2 二种特有情状的拍卖

2.1.1主要讲的是有个别家常view的层级结构的path构造情势,然而有一些独特情形供给专门的考虑处理:

  • UITableViewCell

由于UITableViewCell具有可复用的建制,当叁个页面中在不停滚动的时候,cell在频频的复用,假诺还选拔2.1.1中牵线的点子来获取index索引值话,那么会挑起整个页面无埋点数据收集的混杂。

当获得当前UITableViewCell的index时,能够利用indexPath参数进行替换,这一个参数可精确的拿走section和row的值,唯一的附和每一种cell。唯一层级路径的样式可以自定义配置,哈勃勒Data的装置方式为:类名+(section:
row:),下边给出三个示范:

MyTableViewCell(section:0 row:7)
  • UICollectionViewCell

UICollectionViewCell的path生成原理同UITableViewCell,哈勃勒Data的装置形式为:类名+(section:item:),下边给出1个演示:

MyCollectionViewCell(section:0 item:7)
  • UIControl

实则UIButton也毕竟一种平凡view的一种,半数以上情状下,使用上述的层级结构path以及页面类名的组成能够唯一的规定当前UIControl的唯一标识符,可是有一种奇特的地方,当作为UINavigationItem时会出现特殊意况,上边包车型地铁所提交的五个例证。

bar1

bar2

当点击第③个NavigationBar的动手的按钮时,得到的层级路径为:

...UIViewControllerWrapperView(0)_UIView(0)_UILayoutContainerView(0)_UINavigationBar(0)_UIButton(1)

浅析可见,右边的设置按钮的目录为0,所以左侧的按钮索引为1。同时获取的脚下页面为:UINavigationController。

当点击第②个页面包车型地铁同三个类型的按钮时,即一律标有数字7的item时,此时获取的层级路径为:

...UIViewControllerWrapperView(0)_UIView(0)_UILayoutContainerView(0)_UINavigationBar(0)_UIButton(2)

能够发现此时的按钮的目录变成了2,已经区别于上述首个NavigationBar的同1个按钮的层级路径了,经过分析,索引值为1的按钮是最右面包车型大巴表格的相当item,经过验证能够获取其层级路径:

...UIViewControllerWrapperView(0)_UIView(0)_UILayoutContainerView(0)_UINavigationBar(0)_UIButton(1)

获得的页面为:UINavigationController。

实际上那种页面很常见,由于页面包车型客车切换,NavigationBar上的一对按钮的岗位只怕顺序会打乱,导致同1个效应的NavigationItem已经不能够分明标识唯一,就算是收获了现阶段按钮所在的页面也无从区分,因为获取的都以UINavigationController。从上面的解析能够看看,那种状态甚至会导致严重混乱的数据收集。

实则仔细分析一下,要是条分缕析得出该UIControl是在UINavigationBar上,则无需安装其对应的index值,即上述的享有navigationItem的层级结构路径都为:

...UIViewControllerWrapperView(0)_UIView(0)_UILayoutContainerView(0)_UINavigationBar(0)_UIButton

即都不做区分。

哈勃勒Data选择增添一种新的性质来分别各样item,其实很引人侧目能够看出来,那一个item的推行的action肯定是不相同的,所以取其action属性来不一致,最后的差别格局如下:

path(...UIViewControllerWrapperView(0)_UIView(0)_UILayoutContainerView(0)_UINavigationBar(0)_UIButton)&actions(button1Click:)
path(...UIViewControllerWrapperView(0)_UIView(0)_UILayoutContainerView(0)_UINavigationBar(0)_UIButton)&actions(button2Click:)

那般,哈勃勒Data就足以确切的分别分歧的item了,同时落到实处均等种意义的item,由于其action相同,所以也会准确的标识其唯一性。

  • UIAlertController

鉴于差其他UIAlertController在甄选分明、撤废等选取时,采取的开展唯一层级路径判定的view需求开始展览自然的拍卖,同时为了确定保证差异的UIAlertController处于同一任务的取舍的埋点伊夫ntID差异,那里在组织唯一标志字符串的时候还要投入该UIAlertController的message和title新闻。3.5小节中会举办相关无埋点采集的介绍。

  • viewController的嵌套

貌似景色下,普通的view只需依据一般的层系路径收集index即可,可是当存在pageViewController时,如下图所示分别交付了一个横向滚动(以公司考拉app为例)和纵向滚动(以店堂严选app为例)的app的截图的言传身教:

事实上可以看出,pageViewController会应用到丰裕多彩app中,所以那类app在应用过程中的无埋点问题尤为要考虑。

圈选视图绑定事件

视图唯一标识viewPath生成,上述手续已经获得了圈选的视图。怎么着规定视图的view帕特h也是重中之重。view帕特h需求总体应用唯一,才方可分别区其余风云。由于是无码,所以只能从视图自身的性质去分析。大家得以把App的视图结构通晓成树的定义,树的根节点是UIWindow,树的枝干由UIViewController和UIView组成,叶子节点都以UIView。那么从根节点到叶子节点的路线能够看做是绝无仅有的。相当于视图的viewPath。上边介绍下完毕的逻辑,view帕特h由两有个别组成,第①有个别是节点路径,另一有的是与之相应的节点index。节点路径是由各种节点的Class拼接而成,节点index,正是节点在父节点中的下标,比如子视图在父视图的subviews数组中的下标。下图是遍历节点的逻辑图。
图片 2
总括节点的index,那么些手续,有种特殊的视图需求留意,可复用视图的index是跟数据源相关的,比如UITableViewCell,此类视图的index无法动用父视图的subviews的下标代替,应该选用数据源的下标代表,比如cell的indexPath.section:indexPath.row。上边给出一个简单易行视图和可复用视图的viewPath的例证。TestViewController-UIView-UIButton&0-0-0和TableViewController-UITableView-UITableViewCell&0-0-1:0。
什么样检查和测试用户触发了绑定了事件ID的视图也是重要,此处运用的焦点技术是runtime中Method
Swizzle。上面介绍一下针对性分裂类型的控件,怎么样hook相应的章程。

  1. UIControl类型的控件hook – (void)sendAction:(SEL) to:(id)target
    for伊芙nt:(UI伊夫nt *)event
  2. UIScrollView,UITextView,UITableView,UICollectionView
    类型的控件,先hook -(void)setDelegate:(id)delegate
    方法,然后再hook想要采集事件的代办方法,例如 textViewDidBeginEditing
    、tableview:(UITableView *)tableview
    didSelectRowAtIndexPath:(NSIndexPath *)indexPath 等。
  3. 带手势事件的视图 hook
    -(void)addGestureRecognizer方法,并在情势完毕中给手势对象添加新的target和action
    ,- (void)addTarget:(id)target action:(SEL)action。
(1) 各类子页面包车型客车controller分歧?

设若pageViewController中的各样子页面差别,固然一而再2.2节HubbleData会加盟页面controller的音信来分别那几个分化的子页面,不过或然会由于种种子页面参预的各类分裂,导致每回app进来的时候同二个页面包车型客车轩然大波会取得不一样的伊夫ntID,举例来说美赞臣(Meadjohnson)下,如上航海用教室1所示,比如前八个子页面是ViewController1,
ViewController2, ViewController3,
ViewController4,那类pageViewController除非设置三个子页面同时预加载出来,那么此时的拿走的层级路径为:

ViewController1对应路径为:superview(0)_subControllerView(0) 
ViewController2对应路径为:superview(0)_subControllerView(1)
ViewController3对应路径为:superview(0)_subControllerView(2)
ViewController4对应路径为:superview(0)_subControllerView(3)

可是app基本都不会预加载出全数页面,对于用户不感兴趣的页面完全没需求二次性全体加载处理,只有当用户挑选了该条款时,该对应的子页面才会加载出来,假如明日用户点击的逐条是ViewController1,ViewController3,ViewController4,ViewController2,由于addChildViewController恐怕addSubView的依次的变更,那么此时获得的层级路径为:

ViewController1对应路径为:superview(0)_subControllerView(0) 
ViewController2对应路径为:superview(0)_subControllerView(3)
ViewController3对应路径为:superview(0)_subControllerView(1)
ViewController4对应路径为:superview(0)_subControllerView(2)

能够窥见,index值变了,层级路径不唯一了,那么无埋点采集的伊夫ntID恐怕会由于用户选择页面顺序的不等而各异,造成埋点数据的紊乱。

HubbleData对于此类页面的拍卖是,境遇此类页面,即不用index标注,所以晤面并的标识成:

ViewController1对应路径为:superview(0)_subControllerView 
ViewController2对应路径为:superview(0)_subControllerView
ViewController3对应路径为:superview(0)_subControllerView
ViewController4对应路径为:superview(0)_subControllerView

再三再四能够透过分歧的页面包车型大巴controller的类名获取其分裂的绝无仅有标识字符串。

总结

无码埋点的关键技术,就是以上分析的几点,首先通过可视化圈选获得供给绑定事件视图,并生成唯一标识viewPath,通过hook系统控件的法子,得到用户触发的视图,生成视图的viewPath与当地的轩然大波列表比对,比对成功则上传viewPath对应的事件。

(2) 各类子页面包车型大巴controller相同?

骨子里做过此类页面包车型大巴基本应该都耳熟能详,很多气象下子页面都以国有的,只可是是填充的model分歧而已,那么际遇那种情况,假若是依照难题1的消除思路,尽管如约2.2得到了近来页面包车型地铁controller,那么照旧不可能区分出那么些页面,所以照旧须要设置新的有着辨识度的index。

实际通过pageViewController可以窥见,用户能够通过左右滑动或许前后滑动来切换子页面,表明全部的子页面都是放到在三个scrollView之中,那么就能够从那些scrollView入手,重新显然index。上面给出哈勃勒Data化解这一个难题的艺术。

一早先想行使当前scrollView的contentOffset整除此pageViewController的页面宽度和冲天所获取的值作为区分子页面包车型地铁index,然而考虑到或许contentOffset的接二连三变化以及子页面横跨pageViewController整数倍宽度的疆界时,恐怕会促成获取的index不唯一的气象,所今后来应用该子页面包车型地铁发轫地方整除pageViewController的照应地宽度和中度获得相应地index。具体的兑现如下,在那之中controller为当前的页面:

 if (view == controller.view || view == controller.view.superview) {
      NSInteger index_x = view.center.x / [view superview].frame.size.width;
      NSInteger index_y = view.center.y / [view superview].frame.size.height;
      NSString *path = [NSString stringWithFormat:@"%@(indexx:%ld indexy:%ld)",  
                        NSStringFromClass([view class]), index_x, index_y];
  } 

从而一律针对上述(1)所付出的五个ViewController1,优化后的到的唯一的标识为:

ViewController1对应路径为:superview(0)_subControllerView(indexx:0 indexy:0)
ViewController2对应路径为:superview(0)_subControllerView(indexx:1 indexy:0)
ViewController3对应路径为:superview(0)_subControllerView(indexx:2 indexy:0)
ViewController4对应路径为:superview(0)_subControllerView(indexx:3 indexy:0)

如此那般固然各类子页面包车型大巴controller相同,也能经过优化后的index来差别各种不一样的子页面。当然这种只是本着嵌套scrollView的子页面包车型大巴图景,然则能消除抢先二分一的此类难点,对于有些其它的特殊意况等,需详细分析页面布局进行剖析。

2.2 当前页面controller的拿走

看上去,大部分动静下2.1的view的层级结构path已经基本明确view的绝无仅有标识字符串,可是普遍存在这么一种情形,当同一个页面跳转多个不等的页面时,假诺那七个不等的页面上都取第②个按钮的层级路径,得到的简化后的结果都如下所示:

.../UINavigationTransitionView(0)/UIViewControllerWrapperView(0)/UIView(0)/UIButton(0)

是心有余而力不足实行那八个页面上的按钮区分的,其实页面包车型客车类名是分别的二个最直接的点子。哈勃勒Data是遵守下边包车型客车主意赢得某些view所在的controller的类名的。

获得当前controller示例

将view的层级路径结合当下页面包车型地铁称谓,已经能够化解掉大多数的绝无仅有标识字符串的标题了。

那里要求小心的一些是,当页面类型一样,只是填充的model分歧时,比如浏览商品详情时,所进入的页面都以二个,只是model差异,最近哈勃勒Data对那种场馆权且未做拍卖。后续可参看文章3.2节UIViewController的无埋点采集,对有个别页面,用户能够自定义诸如screenTitle的字段,定义该页面包车型地铁名号,比如screenTitle包罗产品唯一ID时,此时将该字段参与唯一标识字符串中即可区分。近年来那块还未做相关处理,那里只是提供二个粗略的缓解思路。

>三 、无埋点的采访的兑现

3.1 AOP 简介

上边讲一下无埋点的现实贯彻,用到的严重性是AOP(Aspect-Oriented-Programming),面向切面编制程序,面对的是处理进度中的有些步骤和方法。在运行时,动态的将代码插入到类的制定措施、钦命地点上的编制程序思想就是面向切面编制程序。熟谙iOS
Runtime的应有很明白,相关的介绍小说也很多,那里不再过多的废话。

哈勃勒Data无埋点的贯彻重点就是借助AOP,hook对应类的艺术,并在原完毕代码的根底上插入自个儿定义的埋点的代码,当该类的被hook的函数执行时,就能落到实处无埋点数据收集的机能。下边给出HubbleData里面Method
Swizzling的一个简易的实现。

Method Swizzling

上述代码只是给出了一个简练的完结的逻辑结构,new_swizzledMethod也只是selector没有参数的图景(除去self和_cmd),真正在埋点的处理进程需求考虑的情事相比较多。

3.2 UIViewController的无埋点采集

根本是收集页面包车型地铁生命周期,那里哈勃勒Data选取的是hook
UIViewController的view威尔Appear方法,根据3.1交付的艺术:

 [DASwizzler swizzleBoolSelector:@selector(viewWillAppear:)
                         onClass:[UIViewController class]
                       withBlock:executeAppearBlock];

当view威尔Appear函数执行时,插入埋点的代码。哈勃勒Data的宏图方法为:

伊夫ntID设置为一定的da_screen,即不会经过EventID来分别各类页面包车型地铁音讯,哈勃勒Data将逐一页面包车型地铁分别音讯放在了properties中,在那之中properties的装置为:

(1) $screenName 为当前页面的名称;
(2) $screenTitle 为当前页面的title,可为空;

再者哈勃勒Data SDK提供了3个protocol <DAScreenAutoTracker>

即用户能够经过兑现该protocol,哈勃勒Data
SDK会将screenTitle重临的值作为页面包车型客车名号,trackProperties重临的质量加入对应页面包车型大巴da_screen事件的属性中,作为用户访问该页面时的风波性质,screenUrl再次来到的字符串作为页面包车型大巴Url,用于做一些页面之间相互跳转的辨析等。

再正是增添了白名单设置,有部分UIViewController的音讯用户不想征集,能够因而设置白名单的法门,将部分不想征集的UIViewController过滤掉,比如说SFBrowserRemoteViewController,UIInputWindowController等连串自带的有些。

最终会调用track伊芙nt记录该采访的事件,同上述介绍的代码埋点一样,调用的法子如下:

[[DATracker sharedTracker] trackScreenEvent:@“da_screen” withAttributes:properties];

在那之中properties即为上述要搜集的有个别性情。

3.3 UIControl的无埋点采集

针对UIControl,哈勃勒Data采取的是hook
UIControl的sendAction:to:for伊夫nt:方法。由官方文书档案可见,在UIControl执行相应的action时都会率先调用sendAction:to:forEvent:方法,达成如下:

control

考虑到UIControl的子类较多,所以哈勃勒Data选择了里面使用较多的二种举行了不相同平常的解析:首假诺UITextField、UIButton和UISwitch,其他的一时半刻未做尤其分析。具体的埋点的采访安排为:

任由哪个种类UIControl,伊夫ntID均选用的是第①有些介绍的绝无仅有标识字符串的SHA256编码值,不过相关采访properties有所差别。

3.3.1 UITextField

UITextField是UIControl的三个子类,由于UITextField涉及到用户的隐情相比多,比如用户名、密码、聊天文本等,所以哈勃勒Data不会对此类的UITextField举行埋点的采访。

哈勃勒Data首要收集的是UISearchBar中的UITextField,即UISearchBarTextField,并获取搜索的文本内容,那对于有些电商类的App来说,能够较好的解析用户感兴趣的货物等,那是当做HubbleData
SDK无埋点的2个须求。

hook住sendAction:to:forEvent:后,如果对UISearchBarTextField的所有actions都进行hook的话,那么_searchFieldBeginEditing、_searchFieldEnd艾德iting等全部的action产生的时候都会进展数据的采访,会征集到许多无效的音讯,导致采集的数量错乱。HubbleData
SDK唯有当_searchFieldEndEditing
action爆发时才会议及展览开埋点,收集的properties为:

(1) type 为UIControl采集的事件类型,这里设置为searchBarEvent;
(2) page 为当前页面的名称,用于前端显示用;
(3) searchText 为_searchFieldEndEditing发生时采集到搜索框的搜索文字(此字段不为空);

如此那般就能对搜索框实行无埋点采集,并能收集搜索的文件内容。此办法只是在_searchFieldEnd艾德iting发生时征集数据,有恐怕该action执行业作风尚未尽兴真正的探寻操作,恐怕会与事务数据库的数码有出入,可是也能够比较准确的分析用户感兴趣的摸索内容。

3.3.2 UIButton

UIControl中运用最多最广大的是UIButton,由此对UIButton的征集很是重庆大学。在动用UIButton的时候可以肆意的设置其title等质量来代表事情逻辑的不比情形。那里能够举一个简易的例子:基本app的记名页面,在用户名和密码都未输入时、都输入时以及登录中逐条状态,登录按钮的title、titleColor等属性可能都以见仁见智的,即各种button的体制都表示着一种体制,不过得到的伊芙ntID是同等的。针对此种意况,哈勃勒Data会加盟title、titleColor作为属性值,以有益后台举办越发的分析。

当按钮的三种境况只是三种不一致的背景图片时,比如天涯论坛或者微信的点赞等,其实是更换了一种背景图片,针对对那种意况处理,哈勃勒Data则会得到图片的imageName作为内部壹特性能。

(1) type 为UIControl采集的事件类型,这里设置为buttonEvent;
(2) page 为当前页面的名称,用于前端显示用;
(3) title 为当前按钮的title;
(4) titleColor 为当前title的color,会转换成字符串的形式,rgba(r, g, b, alpha);
(5) imageName 为当前按钮的背景图片的name;
(6) frame 为UIButton的frame,用于分析同类元素,会转换成字符串的形式,rect(x, y, width, height);

可以看到,哈勃勒Data还采集了该view的frame信息,首要是用来分析同类成分用的,下图给出一个大约的言传身教:

button

现阶段有四个已关怀的出品,当想计算用户全体点赞的风浪时,由于各类点赞的按钮都地处一个UITableViewCell中,在前边介绍的拿走层级唯一路径UITableViewCell时的卓殊规处理,由于各种按钮所在的cell的row分裂,所以得到的每种按钮的轩然大波的唯一伊芙ntID都是例外的,这样后端在分析的时候,不能归类同类成分。当哈勃勒Data给出frame时,后端可以依据frame归类出同一类按钮的轩然大波,具体的归类策略这里不再介绍。

3.3.3 UISwitch

看似于UIButton,只然而那里要收集switchState,即眼下的开关状态,具体的收集属性为:

(1) type 为UIControl采集的事件类型,这里设置为switchEvent;
(2) page 为当前页面的名称,用于前端显示用;
(3) switchState 为switch的开关状态;
3.3.4 其余UIControl

任何的只是采访type,page属性,方今未做过多的拍卖。

3.4 UITableView和UICollectionView的无埋点采集

本着UITableView和UICollectionView,哈勃勒Data接纳的是先hook
UITableView和UICoolectionView的setDelegate:方法,然后找到相应的delegate,然后再hook
delegate类中的tableView:didSelectRowAtIndexPath:方法和UICollectionView的collectionView:didSelectItemAtIndexPath:方法。那里以UITableView为例:

tableview

伊芙ntID依照上述介绍的方法取得,只不过那里要注意的是,获取的并不是UITableView的绝无仅有标识字符串而是对应的点击的cell的唯一标识字符串。采集的properties为:

(1) type 为UITableView采集的事件类型,这里设置为tableViewSelectEvent;
(2) page 为当前页面的名称,用于前端显示用;
(3) section 为点击的cell所在的section;
(4) row 为点击的cell所在的row;

3.5 UIGestureRecognizer的无埋点采集

在iOS开发中,常常会采纳部分手势来拍卖部分点击的操作,所以也有必不可少对UIGestureRecognizer举行hook。哈勃勒Data
并不是一贯针对UIGestureRecognizer那些类举行hook,而是hook
UIView类的addGestureRecognizer:方法,达成如下:

gesture

透过hook
addGestureRecognizer:方法,能够拿走该UIView所添加的UIGestureRecognizer,那里只对UITapGestureRecognizer和UILongPressGestureRecognizer举行拍卖,其他的手势暂未做处理。获得相应的UIGestureRecognizer,添加多个action,当该手势执行的时候,同样会执行该action,在action中推行埋点的操作。

此地收获的是UIGestureRecognizer所在的UIView的绝无仅有标识标识字符串编码作为伊夫ntID,采集的属性为:

(1) type 为UIGestureRecognizer采集的事件类型,这里设置为gestureTapEvent;
(2) page 为当前页面的名称,用于前端显示用;

UIAlertController的异样处理

此处要求对UIAlertController做1个详细的认证,因为UIAlertController在点击诸如撤除、鲜明的选项按钮时,也会进行手势的埋点采集,然而在iOS9和iOS10上某些有个别差异。

那边先以iOS9为例,其target是效果在_UIAlertControllerView这几个体系的私有类上的,若是一直对那些_UIAlertControllerView实行唯一标识字符串的结构,则撤废和分明选项获得的伊芙ntID是如出一辙的,那样将不能够准确的剖析出用户的取舍,所以必须以各个选项view作为独立的唯一标识字符串进行辨析才能精确区分。通过获取_UIAlertControllerView的_actionViews变量,就能博取各类选项的view,那里要做二个不难易行的点击坐标获取,判断所点击的区域位于的actionView,具体落到实处如下:

此处在原则判断时设定gesture.state ==
UIGestureRecognizerStateBegan,是出于UILongPressGestureRecognizer会延续五遍调用action,因而那里必要投入事件的情事进行区分,幸免实行一次相同的多少收集。

iOS10下的UIAlertController的当中贯彻做了一部分变动,其target变换到在_UIAlertControllerInterfaceActionGroupView那几个系统的私有类上的,然后供给开始展览一定的处理,获取UIInterfaceActionSelectionTrackingController的_representationViews变量,遍历获得各种选项的view,具体得以实现如下:

经过上述的辨析能够窥见,那样纵然能分别同一个UIAlertController的两样的操作选项,可是或许不能区分出差别UIAlertController的处于相同职位的选项,所以那边还要到场UIAlertController额外的质量信息来分别。

眼下也有提过,能够很简单的想到UIAlertController的message和title能够较好的进展区分,所以在原本的层级路径和当下页面包车型大巴底蕴上,还要加上message和title以整合唯一标识字符串。给出1个样例:

path(UIWindow(0)__UIAlertControllerView(0)_UIView(0)_UIView(0)_UIView(0)_UICollectionView(0)__UIAlertControllerCollectionViewCell(section:0 item:0)_UIView(0)__UIAlertControllerActionView(0))&controller(UIAlertController)&message(确认退出群聊吗?)&title(退群)

四、总结

小说首要介绍了哈勃勒Data无埋点SDk在iOS端的设计与落到实处,涉及的重要性内容:事件唯一ID的鲜明和一些无埋点的兑现,当然在无埋点SDK的设计开发中还遇上了不以为奇的难题。鉴于小说的篇幅已经较长,一些题材的化解以及关键技术的兑现,比如精准渠道追踪、hook争持消除、代码埋点的贯彻、荧屏系列化以及可视化圈选部分的内容,本篇文章不再介绍,将会在继承小说中接二连三介绍。