乘势大数据时代的过来澳门金冠网站主页,近年来在背负集团的HubbleData的埋点SDK的开发职务

0 引言

新近在担负公司的HubbleData的埋点SDK的开发职分,产品的雏形其实在几年前就曾经有了,公司里面的例如考拉、易信、LOFTER、美学、漫画等多款产品都已连接使用。

下图给出HubbleData SDK某个应用的有些分析的显得页面:

(1)概览示意图

事件

(2)事件分析示意图

事件

(3)实时分析示意图

事件

其它HubbleData平台还存有留存分析、漏斗分析、粘性分析、数据看板等多种功力,方便有关负责人士对成品用户作为开展尤其的追究分析。

老版本的SDK的安插性是代码埋点达成的,即便对于一些相比成熟的成品,代码埋点完全能够达到产品方的急需,可是对于有些新开行或者需频仍改变的须要的新产品等,考虑到其保证的老本大,代价高等缺点,HubbleData无埋点SDK的宏图就显得愈发重大了。

本身根本担负iOS端无埋点以及可视化圈选的做事,小说主要系统讲授一下HubbleData无埋点SDK在iOS端的设计与落到实处和有些巢毁卵破问题的解决,后续将针对所有埋点的完毕流程与可视化圈选等情节再作分享。

一、埋点简介

By Cobub OP
Team
 in 博客未分类

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

埋点的法子分为三类:代码埋点、可视化埋点和无埋点。这里几乎的牵线一下三种埋点格局:

(1)
代码埋点即是在代码的关键部位植入所要收集数据的N行代码,须求挖开产品本身,深入精晓产品的作业逻辑及项目布局,上边代码模拟展现的即是点击提交订单的时候HubbleData
SDK代码埋点;

代码埋点示例

(2)
可视化埋点即用可视化交互的章程圈选出所要采集数据的控件,当用户作为暴发时,即可收集到对应的埋点数据。比较于前方的代码埋点而言,可视化埋点可以解决代码埋点代价大费用高的题目,不过无法灵活的自定义埋点属性。

可视化埋点流程

(3)
无埋点也叫全埋点,即不必要用户积极埋点,可以搜集用户所有的操作行为,同样运用可视化圈选,用户可以得到所想采集的埋点数据,可以解决可视化圈选中数量不可回溯的题目。下图给出了无埋点多少收集的大概流程。

无埋点数据搜集流程

HubbleData
SDK的设计重点是代码埋点结合无埋点的多寡搜集格局,其中也论及到可视化埋点中的显示器系列化及事件绑定机制,本文主要介绍一下无埋点的陈设与落到实处。

11
hours ago  0  59

1.2 无埋点SDK设计详细流程

下图给出HubbleData无埋点SDK在iOS端的设计完毕:

无埋点详细安插流程

从上图能够看到,HubbleData的无埋点是在代码埋点的底子上贯彻的,所处无埋点的困难也就集中在偏下多少个方面:

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

正文主要就那八个方面展开剖析,第二部分关键讲一下轩然大波唯一ID的确定,第三有些敬爱讲一下无埋点的采集的兑现,紧假若各类风浪发生采集的空子以及待采集的属性的布置。

HubbleData
SDK还涉嫌到许多别样成效,包涵显示器连串可视化、代码埋点、精准渠道追踪等,这里不再介绍,前面会陆续分享有关的技能完毕。

乘胜大数目时代的赶来,数据搜集也一度变的进一步首要。前端埋点作为一个比较早熟的数额联网手段被广泛应用着。近来埋点分为二种办法,有码与无码埋点。有码埋点比较易于精通,即调用SDK的API,在代码中插入埋点的连锁代码,达成用户作为采集。由于大家在支付项目标时候,埋点都是手动的,每趟业务须要的改观都要遍地埋点,而无码埋点,即不要求手动插入代码,只须求中期开展有关配置,SDK自动采集用户作为,极大程度防止了因急需变动、埋点错误等原因导致的再一次埋点繁复工作。本文主要介绍无码埋点的技艺已毕。

二、事件唯一ID的确定

为了落到实处在可视化圈选的时的风云的唯一性,每一个无埋点的风云采访都必须有且仅有一个唯一的标识符来区分不一致的事件。差距于代码埋点,用户能够自定义的配备自己所需的伊芙(Eve)ntID,无埋点进程中,必要SDK自己安插每一个采集事件的伊芙ntID,通过可视化圈选的操作,筛选出相应的伊芙(Eve)ntID所对应的数据音信。HubbleData选拔的是协会view唯一标识字符串的点子去唯一的标识这样的一个事件,首要由view的层级结构path路径、该view的四方页面类名以及view所带的有的本身定位属性等结合,并透过SHA256编码来获取唯一的伊芙(Eve)ntID。

上面将完整系统介绍部分事件唯一ID的变更进程。

无码埋点的贯彻流程

澳门金冠网站主页 1
1.可视化视图圈选,在页面上会出现转移的圆形,拖动圆圈至想安排事件的控件上,将会弹出输入事件的弹框。
2.在上一步的弹框中输入自定义的轩然大波名称,名称将会和视图的viewPath绑定起来。viewPath是视图的唯一标识,在下文司令员详细讲解。
3.用户点击了控件,判断控件是或不是绑定过事件,如绑定则开展事件上传。

2.1 控件的层级结构path构造

完毕流程中的技术点

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

层级结构path紧假设基于页面的控件树构造而成,每个view都有superview与subviews的性能,将每一个view的superview作为树的父节点,将其subviews作为子节点,那样就能把全路app上的具备view组成一棵巨大的控件树,其中树的顶层是UIWindow,然后是每一个view节点依次向下举办。下图给出一个简练的控件树的构造图。

空中树结构

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

不同类

同类

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

UIView_UILabel
UIView_UIButton

只是的确的页面是不会像绝妙中的所有控件都是见仁见智品类的,可以说那种相当情况基本不存在,借使依旧依据上述的艺术来组织路径的话,七个UILabel都会被标识成UIView_UILabel,这明显不可能区分七个控件。因而唯有是各样控件节点的门路名称是无法唯一标识那些控件的,那里HubbleData参加了此控件节点在父视图中的index。比如上图2,可以将几个UILabel标识为:

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

此地假若父视图是index为0的一个节点,那样就足以完全的界别出三个控件了。

那就是说余下的题目就是种种UIView index索引值的确定。

每个UIView都有subviews属性,每一个子视图都有一个被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数组中的索引就是HubbleData要拿的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这几个数组中获取其对应的索引值,而是举办一个简短的同类归并再取索引值,一个很粗略的处理。

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的依次沟通了,或者去除了第二个,此时仍旧会得到一些不确切的层级路径。此题材会连续解决,会逐步引入误差容量和相似度这么些概念,即若是在误差范围内,则会举办进一步的协作,具体的化解方案本篇不在介绍。

可视化视图圈选完结

自定义UIWindow的子类,当做悬浮小圆圈,添加UIPanGestureRecognizer手势,按照手势的移动,设置悬浮框的移动。手势停止时得到悬浮窗宗旨点的坐标。
遍历主window上的子视图,找到包涵上述悬浮窗大旨点且能响应用户交互的最里层视图,即为用户可以圈选的视图。
参照iOS控件的音信传递链,有个为主措施。UIView hitTest:(CGPoint)point
with伊夫(Eve)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。唯一层级路径的样式可以自定义配置,HubbleData的安装方法为:类名+(section:
row:),上边给出一个示范:

MyTableViewCell(section:0 row:7)
  • UICollectionViewCell

UICollectionViewCell的path生成原理同UITableViewCell,HubbleData的安装方法为:类名+(section:item:),上面给出一个演示:

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的按钮是最右侧的报表的不胜item,经过认证可以得到其层级路径:

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

获取的页面为:UINavigationController。

实则这种页面很广泛,由于页面的切换,NavigationBar上的有的按钮的岗位也许顺序会打乱,导致同一个意义的NavigationItem已经不可能确定标识唯一,就算是得到了眼前按钮所在的页面也不能区分,因为获取的都是UINavigationController。从上边的辨析可以阅览,那种情形如故会促成严重混乱的数目收集。

骨子里仔细分析一下,如若条分缕析得出该UIControl是在UINavigationBar上,则无需安装其相应的index值,即上述的保有navigationItem的层级结构路径都为:

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

即都不做区分。

HubbleData选取伸张一种新的属性来分别各类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:)

如此那般,HubbleData就足以规范的界别区其他item了,同时落成平等种功效的item,由于其action相同,所以也会规范的标识其唯一性。

  • UIAlertController

是因为差其余UIAlertController在增选确定、裁撤等选项时,选择的举行唯一层级路径判定的view必要展开自然的拍卖,同时为了有限协理不相同的UIAlertController处于同一职位的精选的埋点伊芙(Eve)ntID分化,那里在结构唯一标志字符串的时候还要插足该UIAlertController的message和title新闻。3.5小节中会举行相关无埋点采集的牵线。

  • viewController的嵌套

相似意况下,普通的view只需根据一般的层次路径收集index即可,不过当存在pageViewController时,如下图所示分别交付了一个横向滚动(以集团考拉app为例)和纵向滚动(以店堂严选app为例)的app的截图的演示:

事实上可以看看,pageViewController会应用到种种各种app中,所以那类app在使用进度中的无埋点问题进一步要考虑。

圈选视图绑定事件

视图唯一标识viewPath生成,上述手续已经获得了圈选的视图。怎样确定视图的viewPath也是任重(英文名:)而道远。viewPath需求所有应用唯一,才可以分别区其余轩然大波。由于是无码,所以只能从视图本身的习性去分析。大家得以把App的视图结构精晓成树的定义,树的根节点是UIWindow,树的枝干由UIViewController和UIView组成,叶子节点都是UIView。那么从根节点到叶子节点的路子可以视作是绝无仅有的。也就是视图的viewPath。下边介绍下达成的逻辑,viewPath由两局地组成,第一局地是节点路径,另一片段是与之相应的节点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伊夫(Eve)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进来的时候同一个页面的风浪会拿走不一样的伊芙(Eve)ntID,举例来说圣元(阿博特)下,如上图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。下边给出HubbleData解决那么些题材的措施。

一伊始想选用当前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)

是无能为力进展那多个页面上的按钮区分的,其实页面的类名是分其他一个最直接的不二法门。HubbleData是按部就班下边的格局取得某个view所在的controller的类名的。

赢得当前controller示例

将view的层级路径结合当下页面的名号,已经可以缓解掉大多数的绝无仅有标识字符串的题材了。

这边须要注意的一点是,当页面类型一样,只是填充的model不一致时,比如浏览商品详情时,所进入的页面都是一个,只是model差别,如今HubbleData对那种情景临时未做处理。后续可参看小说3.2节UIViewController的无埋点采集,对有的页面,用户可以自定义诸如screenTitle的字段,定义该页面的称谓,比如screenTitle包蕴产品唯一ID时,此时将该字段到场唯一标识字符串中即可区分。方今那块还未做连锁处理,那里只是提供一个概括的缓解思路。

>三、无埋点的采集的贯彻

3.1 AOP 简介

上边讲一下无埋点的现实性完成,用到的最首假诺AOP(Aspect-Oriented-Programming),面向切面编程,面对的是处理进程中的某个步骤和章程。在运作时,动态的将代码插入到类的制定办法、指定位置上的编程思想就是面向切面编程。熟谙iOS
Runtime的应当很精通,相关的介绍文章也很多,那里不再过多的废话。

HubbleData无埋点的兑现重大就是借助AOP,hook对应类的法门,并在原完毕代码的底子上插入自己定义的埋点的代码,当该类的被hook的函数执行时,就能兑现无埋点数据搜集的成效。下边给出HubbleData里面Method
Swizzling的一个简便的落到实处。

Method Swizzling

上述代码只是给出了一个简单易行的落到实处的逻辑结构,new_swizzledMethod也只是selector没有参数的情景(除去self和_cmd),真正在埋点的处理进程须要考虑的景观相比多。

3.2 UIViewController的无埋点采集

首借使收集页面的生命周期,那里HubbleData接纳的是hook
UIViewController的view威·尔(W·ill)Appear方法,根据3.1交到的法门:

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

当view威尔Appear函数执行时,插入埋点的代码。HubbleData的筹划艺术为:

伊芙ntID设置为定点的da_screen,即不会经过伊夫ntID来区分各样页面的信息,HubbleData将依次页面的分别音讯放在了properties中,其中properties的设置为:

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

再就是HubbleData SDK提供了一个protocol <DAScreenAutoTracker>

即用户可以通过兑现该protocol,HubbleData
SDK会将screenTitle重返的值作为页面的名称,trackProperties再次回到的性质加入对应页面的da_screen事件的性能中,作为用户访问该页面时的轩然大波性质,screenUrl重回的字符串作为页面的Url,用于做一些页面之间相互跳转的辨析等。

再就是增添了白名单设置,有一部分UIViewController的信息用户不想征集,可以由此设置白名单的点子,将部分不想征集的UIViewController过滤掉,比如说SFBrowserRemoteViewController,UIInputWindowController等种类自带的有些。

说到底会调用track伊夫(Eve)nt记录该采访的风浪,同上述介绍的代码埋点一样,调用的格局如下:

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

其间properties即为上述要采访的有些特性。

3.3 UIControl的无埋点采集

针对UIControl,HubbleData采取的是hook
UIControl的sendAction:to:for伊芙nt:方法。由法定文档可见,在UIControl执行相应的action时都会率先调用sendAction:to:for伊芙nt:方法,已毕如下:

control

考虑到UIControl的子类较多,所以HubbleData选用了里面使用较多的二种进行了格外的解析:紧假使UIText菲尔德、UIButton和UISwitch,其他的临时未做特殊分析。具体的埋点的征集布署为:

随便哪类UIControl,伊芙(Eve)ntID均拔取的是第三片段介绍的唯一标识字符串的SHA256编码值,不过相关采访properties有所差异。

3.3.1 UITextField

UIText菲尔德(Field)是UIControl的一个子类,由于UIText菲尔德(Field)涉及到用户的苦衷相比较多,比如用户名、密码、聊天文本等,所以HubbleData不会对此类的UIText菲尔德(Field)进行埋点的募集。

HubbleData紧要收集的是UISearchBar中的UIText菲尔德(Field),即UISearchBarText菲尔德,并获得搜索的文件内容,那对于有些电商类的App来说,可以较好的辨析用户感兴趣的货色等,那是当做HubbleData
SDK无埋点的一个急需。

hook住sendAction:to:forEvent:后,如果对UISearchBarTextField的所有actions都进行hook的话,那么_searchFieldBeginEditing、_search菲尔德(Field)EndEditing等有着的action暴发的时候都会展开数据的采访,会征集到许多无效的音讯,导致采集的多寡错乱。HubbleData
SDK唯有当_search菲尔德EndEditing
action爆发时才会进行埋点,收集的properties为:

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

这么就能对搜索框举行无埋点采集,并能收集搜索的文件内容。此办法只是在_search菲尔德EndEditing暴发时募集数据,有可能该action执行时不曾尽兴真正的物色操作,可能会与事务数据库的多寡有出入,不过也可以比较准确的辨析用户感兴趣的检索内容。

3.3.2 UIButton

UIControl中行使最多最广大的是UIButton,由此对UIButton的搜集相当重大。在选择UIButton的时候可以任意的安装其title等属性来表示事情逻辑的分歧意况。那里可以举一个概括的事例:基本app的报到页面,在用户名和密码都未输入时、都输入时以及登录中相继状态,登录按钮的title、titleColor等特性可能都是差其余,即每一种button的样式都代表着一种体制,可是得到的伊夫ntID是均等的。针对此种意况,HubbleData会进入title、titleColor作为属性值,以有利于后台举办更进一步的剖析。

当按钮的二种意况只是三种不一致的背景图片时,比如网易仍然微信的点赞等,其实是更换了一种背景图片,针对对那种境况处理,HubbleData则会博得图片的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);

可以观察,HubbleData还搜集了该view的frame信息,紧要是用来分析同类元素用的,下图给出一个简单的言传身教:

button

时下有五个已关怀的出品,当想计算用户所有点赞的轩然大波时,由于各样点赞的按钮都地处一个UITableViewCell中,在头里介绍的获取层级唯一路径UITableViewCell时的卓绝处理,由于每个按钮所在的cell的row分歧,所以拿到的各种按钮的事件的唯一伊芙ntID都是见仁见智的,那样后端在条分缕析的时候,不能归类同类元素。当HubbleData给出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,HubbleData选择的是先hook
UITableView和UICoolectionView的setDelegate:方法,然后找到呼应的delegate,然后再hook
delegate类中的tableView:didSelectRowAtIndexPath:方法和UICollectionView的collectionView:didSelectItemAtIndexPath:方法。那里以UITableView为例:

tableview

伊夫(Eve)ntID根据上述介绍的章程得到,只可是那里要注意的是,获取的并不是UITableView的唯一标识字符串而是对应的点击的cell的绝无仅有标识字符串。采集的properties为:

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

3.5 UIGestureRecognizer的无埋点采集

在iOS开发中,日常会动用部分手势来拍卖部分点击的操作,所以也有必不可少对UIGestureRecognizer举行hook。HubbleData
并不是直接针对UIGestureRecognizer这一个类进行hook,而是hook
UIView类的addGestureRecognizer:方法,完毕如下:

gesture

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

此处得到的是UIGestureRecognizer所在的UIView的绝无仅有标识标识字符串编码作为伊夫(Eve)ntID,采集的习性为:

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

UIAlertController的奇异处理

那边须求对UIAlertController做一个详细的验证,因为UIAlertController在点击诸如取消、确定的选项按钮时,也会举办手势的埋点采集,但是在iOS9和iOS10上有些有些差别。

此间先以iOS9为例,其target是效益在_UIAlertControllerView那几个种类的私有类上的,如若直接对那么些_UIAlertControllerView举办唯一标识字符串的结构,则打消和确定选项得到的伊芙(Eve)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以结合唯一标识字符串。给出一个样例:

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(退群)

四、总结

文章首要介绍了HubbleData无埋点SDk在iOS端的设计与落到实处,涉及的关键内容:事件唯一ID的确定和局地无埋点的贯彻,当然在无埋点SDK的统筹开发中还赶上了丰盛多彩的问题。鉴于文章的字数已经较长,一些题材的化解以及关键技术的兑现,比如精准渠道追踪、hook争辩解决、代码埋点的贯彻、显示器连串化以及可视化圈选部分的内容,本篇小说不再介绍,将会在连续小说中持续介绍。

相关文章