埋点概述

埋点概述

确保数据的正确性、完整性和及时性

埋点方式

代码埋点(死埋点)
  • 优点
    • 精准埋点
    • 可以方便灵活的自定义事件 和属性
    • 可以获取更多的业务属性
    • 可以满足高度自定义分析需求
  • 缺点
    • 埋点成本高
    • 后期维护吃力
全埋点
  • 优点
    • 埋点成本较低
    • 页面调正发生变化不需要进行调整
  • 缺点
    • 无法采集业务相关的数据
    • 无法满足精细化需求
  • 采集的事件
    • 应用启动
    • 页面浏览
    • 事件点击
应用状态
  • Active
    • 前台活跃状态。指应用程序正在前台运行,可接收事件并
      进行处理。这也是一个 iOS 应用程序处于前台的正常模式
    • UIApplicationDidBecomeActiveNotification 通知来实现
      AppStart 事件全埋点,因此均会触发 AppStart 事件。在解决这个问题之前,我们先看另一个现象:不管是冷启
      动还是热启动,系统均没有发送 UIApplicationWillResignActiveNotification 通知。
      因此,只要在收到 UIApplicationDidBecomeActiveNotification 通 知 时,判 断 之 前 是 否 收 到 过 UIApplicationWillResignActiveNotification 通 知,若 没 有 收 到,则 触
      发 AppStart 事件;若已收到,则不触发 AppStart 事件。
      这样即可解决上面的问题
  • Background
    • 进入后台状态。指应用程序进入了后台并可执行代码。大
      多数应用程序在被挂起前都会短暂地进入这个状态
    • 注册监听 UIApplicationDidEnterBackgroundNotification n 通知,
      然后在收到通知时触发 AppEnd 事件,即可达到 AppEnd 事件全埋点的效果。
  • Suspended
    • 挂起状态。指应用程序进入后台但没有执行任何代码,系
      统会自动的将应用程序转移到此状态,并且在执行此操作
      之前不会通知应用程序。挂起时,应用程序会保留在内存中,
      但不执行任何代码。当系统出现内存不足情况时,系统可
      能会在未通知应用程序的情况下清除被挂起的应用程序,
      为前台应用程序尽可能腾出更多的运行资源
浏览事件 AppViewScreen 全埋点
  • 时机

    • 通过 UIViewController 的生命周期可知,当执行到 viewDidAppear: 方法时,表示视图已经在屏幕上渲染 完成,也即页面已经显示出来了,正等待用户进行下一步 操作。因此,viewDidAppear: 方法就是我们触发页面浏
      览事件的最佳时机。
  • 技术

    • iOS 的“黑魔法” Method Swizzling 相关的技术 Method Swizzling,顾名思义,就是交换两个方法的实现。简单的来说,就是利用 Objective-C runtime 的动态绑定
      特性,把一个方法的实现与另一个方法的实现进行交换。
控件点击事件 AppClick 全埋点
  • 在 UIKit 框架下,处理点击或拖动事件的 Target-Action 设计模式
    • Target-Action,也叫目标 - 动作模式,即当某个事件发生的时候,调用特定对象的特定方法
  • 时机
    • iOS 中的控件都是 UIControl 类或者其子类,当用户在操作这些控件时,会将消息发送到指定的对象Target 在 UIControl 类中有一个方法:*- (void)sendAction:(SEL)action to:(nullable id)target forEvent:(nullable UIEvent )event;
  • 技术
    • 如果控件被用户操作(比如点击),首先会调用这个方法,并将事件转发给应用程序的 UIApplication 对象。同时,在 UIApplication 类中也有一个类似的实例方法*- (BOOL)sendAction:(SEL)action to:(nullable id)target from:(nullable id)sender forEvent:(nullable UIEvent )event; 如果 Target 对象不为 nil,应用程序会让该 Target 对象调用对应的 Action 方法响应事件;如果 Target 对象为nil,应用程序会在响应者链中搜索定义了该方法的对象,然后执行 Action 方法。
    • *参数 - (BOOL)sendAction:(SEL)action to:(nullable id)target from:(nullable id)sender forEvent:(nullable UIEvent )event;
      • action:Action 方法对应的 selector,即示例中的 btnAction。
      • target:Target 对象,即示例中的 person。如果 Target为 nil,应用程序会将消息发送给第一个响应者,并从第一个响应者沿着响应链向上发送消息,直到消息被处理为止。
      • ender:被用户点击或拖动的控件,即发送 Action 消息 的对象,即示例中的 button。
      • event:UIEvent 对象,它封装了触发事件的相关信息。
  • UITableView 和 UICollectionView点击事件
    • 这 两 个 控 件 的 点 击 事 件,一 般 指 的 是 点 击UITableViewCell 和UICollectionViewCell。而UITableViewCell 和 UICollectionViewCell 都是直接继承
      自 UIView 类,而不是 UIControl 类。因此,我们之前实现 AppClick 事 件 全 埋 点 的 两 个 方 案 均 不 适 用 于UITableView 和 UICollectionView。
  • 时机
    • 如果需要处理 UITableView 的点击操作,需要先 设 置 UITableView 的 delegate 属 性,并 实 现 UITableViewDelegate 协 议 的 - tableView:didSelectRowAtIndexPath: 方法。
  • 技术
    • 使用Method Swizzling 来 交 换 - tableView:didSelectRowAtIndexPath: 方法来实现 UITableView AppClick 事件的全埋点 大 概 思 路:首 先,我 们 使 用 Method Swizzling 交 换
      UITableView 的 - setDelegate: 方法,然后能获取到实现 了 UITableViewDelegate 协议的 delegate 对象,在拿到 delegate 对 象 之 后,就 可 以 交 换 delegate 对 象 的 -tableView:didSelectRowAtIndexPath: 方 法,最 后,在交换后的方法中触发 AppClick 事件
  • 采集手势 点击事件
  • 当我们为一个手势识别器添加一个或者多个 Target-Action 后,在视图上进行触摸操作时一旦系统识别了该手势,就会向所有的 Target 对象发送消息,并执行 Action 方法。虽然
    手 势 识 别 器 和 UIControl 类 一 样,都 是 使 用 了Target-Action 设计模式,但是手势识别器并不会将消息 交由 UIApplication 对象来进行发送。因此,我们无法使
    用与 UIControl 控件相同的处理方式,即通过响应者链的 方式来实现对手势操作的全埋点
  • 时机
    • 手势识别器添加 Target-Action 的方法都是相同的,常见的主要是通过以下的两个方法进行添加。
    • initWithTarget:target action:
    • addTarget:action:
  • 技术
    • 使用Method Swizzling 对这两个方法分别进行交换。我们就实现了手势 AppClick 事件的全埋点方案
时间相关
  • 引入 systemUpTime。系统启动时间,也叫开机时间,是指设备开机后一共运行了多少秒 ( 设备休眠不统计在内 ),并且不 会 受 到 系 统 时 间 更 改 的 影 响。保证统计事件 不受时间影响
数据存储策略

在 iOS 应用程序中,从“数据缓存在哪里”这个维度看的话,缓存一般分为两种类型:

  • 内存缓存
    • 内存缓存,是将数据缓存在内存中,供应用程序直接读取和使用。由于是读写内存,因此读写速度极快。但是,内存缓存
      的缺点也十分明显,由于内存资源比较有效,应用程序在系统中申请的内存,会随着应用程序生命周期的结束而被释放。
      这就意味着,如果应用程序在运行的过程中被用户强杀或者出现崩溃情况,都有可能导致内存中缓存的数据丢失。因此,将事件数据缓存在内存中不是一个最佳选择。
  • 磁盘缓存
    • 磁盘缓存,是将数据缓存在磁盘空间中,其特点正好与内存缓存相反。磁盘缓存容量大,但是读写速度相对于内存缓存来
      说要慢一些。不过磁盘缓存是持久化存储,不受应用程序生命周期的影响。一般情况下,一旦数据成功的保存在磁盘中,
      其丢失的风险就非常低。因此,即使磁盘缓存数据读写速度较慢,但在综合考虑下,磁盘缓存是我们缓存事件数据的最优选择。
      在 iOS 应用程序中,一般通过以下两种方式使用磁盘缓存:文件缓存 数据库缓存(一般是指在 SQLite 数据库)
数据同步策略
  • 策略一:客户端本地已缓存的事件超过一定条数时同步数据(比如 100 条)
  • 策略二:客户端每隔一定的时间间隔同步一次(比如每隔 15s 就同步一次)
  • 策略三:应用程序进入后台时尝试同步本地已缓存的所有数据
    对于 iPhone 用户来说,比较习惯通过按 Home 键或者上滑 HomeBar 让应用程序进入后台。如果此时我们不去尝试同步
    数据,就有可能造成一些数据丢失,因为用户把应用程序进入后台,ta 下次具体什么时候再启动应用程序就不得而知了,
    更有甚者,ta 下一秒可能就把应用程序卸载。因此,每当应用程序进入后台的时候,我们都要尝试同步数据,最大限度的保证数据的完整性。
    我们都知道,苹果对应用程序的后台运行管控的非常严格,如果不做任何处理,应用程序进入后台后大概只有几秒钟的时
    间处理数据。在这么短的时间内,我们完成数据的同步,是完全不可控的,有可能会出现一些无法预料的后果。因此,我们需要更长的后台运行时间。此时,可以借助 UIApplication 类的 - beginBackgroundTaskWithExpirationHandler: 方法,
    这个方法可以让应用程序在后台最多有 3 分钟的时间来处理数据。在网络正常的情况下,这个时间对于我们同步数据而言足够了。

你可能感兴趣的:(埋点概述)