iOS 无侵入埋点的实现

埋点
  • 概念:在iOS开发中,埋点可以解决两大类问题,一是了解用户使用App的行为,二是降低分析线上问题的难度。
  • 常见的埋点方式
    常见的埋点方式主要包括代码埋点、可视化埋点和无埋点三种
  1. 代码埋点主要就是通过手写代码的形式埋点,能很精确的在需要埋点的代码处加上埋点的代码,可以很方便的记录当前环境的变量值,方便调试,并跟踪埋点内容。但存在开发工作量大,并且埋点代码到处都是,后期难以维护等问题。
  2. 可视化埋点,就是将埋点增加和修改的工作可视化了,提升了增加和维护埋点的体验。
  3. 无埋点,并不是不需要埋点,而更确切的说是“全埋点”,而且埋点代码也不会出现在业务代码中,容易管理和维护。它的缺点在于,埋点成本高,后期的解析也比较复杂,再加上view_path的不确定性。所以这种方案不能解决所有的埋点需求,但对于大量通用的埋点需求来说,能够节省大量的开发和维护成本。

其中,可视化埋点和无埋点,都属于无侵入埋点的内容,因为它们都不需要在工程代码中写入埋点代码。所以,采用这样的无侵入埋点方案,既可以做到埋点被统一处理,又可以实现和工程代码的解耦。

运行时方法替换方式进行埋点

iOS开发中,最常见的三种埋点,就是对页面进入次数、页面停留时间、点击事件的埋点。对于这三种常见情况,我们都可以通过运行时方法替换技术来插入埋点的代码,以实现无侵入的埋点方式。

  1. 对于页面曝光埋点,则需要对VC的生命周期方法进行埋点,交换VC的viewWillAppear、viewDidAppear、viewWillDisappear、viewDidDisappear等方法,这样的我们就可以在交互的方法里面加上埋点代码。
    如果区分不同的UIViewController呢?我们可以使用NSStringFromClass([self class])类名字符串来标识不同的UIViewController。

  2. 对于点击事件来说,则需要替换Button的点击事件方法sendAction:to:forEvent,以调用埋点代码。
    和UIViewController生命周期埋点不同的是,UIButton在一个视图类中可能有多个不同的继承类,相同UIButton的子类在不同视图类的埋点也要区分开,这时候,我们可以通过action选择器名NSStringFromSelector(action)+视图类名NSStringFromClass([target class])组合成为唯一的一个标识,来进行埋点记录。

  3. 除了UIViewController、UIButton空间以外,Cocoa框架的其他控件都可以通过这种方法来进行无侵入埋点。以Cocoa框架中最复杂的UITableView控件为例,你可以hook setDelegate方法来实现无侵入埋点。另外,对于Cocoa框架中的手势事件(Gesture Event),我们也可以通过hook initWithTarget:action:方法来实现无侵入埋点。

事件的唯一标识

通过运行时替换的方式,我们能够hook住所有的Objective-C方法,可以说大而全了,能够帮助我们解决大部分的埋点问题。

但是,这种方案的精确度还不够高,还无法区分相同类在不同视图树节点的情况。比如,一个视图下相同UIButton的不同实例,仅仅通过action选择器名+视图类名的组合还不能够区分开。这是,我们就需要一个唯一标识来区分不同的事件。

如何制定出这个唯一标识
  1. 可以通过视图层级的路径来解决这个问题。因为每个页面都有一个视图树结构,通过视图的superview和subviews的属性,我们就能够还原出每个页面的视图树。视图树的顶层是UIWindow,每个视图都在树的子节点上。
    一个视图下的子节点可能是同一个视图的不同实例,比如如果UIView中有两个UIButton是同一个类的不同实例,所以光靠视图树的路径还是没办法确定出唯一的视图标识。
    这时候,索引可以解决这个问题:每个视图在父视图中都会有自己的索引,如果我们再加上这个索引的话,每个视图的标识就是唯一的了。
  2. 视图层级路径加上在父视图中的索引来进行唯一标识,也无法涵盖所有情况
    类似于UITableViewCell这种具有可复用机制的视图,cell会在页面滚动时不断复用,这种情况下加索引的方法还是没用。这时候我们可以通过cell的索引,也就是indexPath的section和row的值去确定cell的唯一性。
  3. UIAlertController也比较特殊,它的特殊性在于视图层级的不固定,因为它可能出现在任何页面中。这时候我们可以通过上层视图+弹窗内容来确定唯一标识。
  4. 其它的情况,我们可以想办法找出相同视图中不同的元素,然后进行组合,最后形成一个能够区别于其他元素的标识来。
  5. 除此之外,如果在程序运行过程中,修改视图的层级和索引,比如执行insetSubView:atIndex:、removeFromSuperView等方法时,我们也无法获得唯一标识,即使只截取部分路径也无法保证后期代码更新时不会动到这个部分。就算是运行时视图层级不会修改,以后需求更新迭代页面频繁的话,视图唯一标识也需要同步的更新维护。

事件唯一标识的准确性难以保障,这也是通过运行时方法替换进行无侵入埋点很难在各个公司全面铺开的原因。虽然无侵入埋点无法覆盖到所有情况,但是还是解决了部分的埋点需求,也节省了大量的人力成本。

小结

通过运行时替换方法来实现无侵入埋点的方案,由于唯一表示难以维护和准确性难以保障的原因,很难被全面采用,一般都只是用于一些功能和视图稳定的地方,手动埋点依然占据大部分场景。

所以说,这种方案不一定是未来的方向。使用clang AST的接口,在构建时遍历AST,通过定义的规则将所需要的埋点代码直接加进入,可能会更合适。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342