帮你快速理解、总结文档立即下载

API 说明

最近更新时间:2026-09-30 17:29:02
本文档已由 AI 辅助审校
我的收藏
本文详细介绍用户体验监控 iOS SDK 的各功能接口,帮助您更灵活、深度地使用 SDK。

初始化接口

SDK 通过 TDEMConfiguration 配置初始化参数,调用 TDEM.start 完成初始化。TDEMConfiguration 除必填的 id 与 url 外,还提供一系列可选参数,详见 SDK 初始化。

上下文与用户

Swift
Objective-C
TDEM.setUser("user-123") // 设置用户
TDEM.clearUser() // 清除用户
TDEM.setDeviceId("device-abc") // 设置设备标识,由宿主提供
TDEM.clearDeviceId() // 清除设备标识,回落 not_set
TDEM.setTags(["region": "ap-shanghai"]) // 批量设置标签
TDEM.removeTags(["region"]) // 批量移除标签
TDEM.clearTags() // 清空标签
[TDEM setUser:@"user-123"]; // 设置用户
[TDEM clearUser]; // 清除用户
[TDEM setDeviceId:@"device-abc"]; // 设置设备标识,由宿主提供
[TDEM clearDeviceId]; // 清除设备标识,回落 not_set
[TDEM setTags:@{ @"region": @"ap-shanghai" }]; // 批量设置标签
[TDEM removeTags:@[@"region"]]; // 批量移除标签
[TDEM clearTags]; // 清空标签
设备标识由业务侧提供,SDK 不会自动生成 IDFV 等系统标识;未设置或传空白时,上报字面量 not_set。也可在 TDEMConfiguration.deviceId 中一并设置。

页面生命周期

Swift
Objective-C
TDEM.startPage(pageID: "checkout") // 进入逻辑页面(LIFO 入栈)
TDEM.leavePage() // 离开逻辑页面(LIFO 出栈)
[TDEM startPageWithPageID:@"checkout"]; // 进入逻辑页面(LIFO 入栈)
[TDEM leavePage]; // 离开逻辑页面(LIFO 出栈)
说明:
startPage / leavePage 需严格成对、按 LIFO 顺序调用。普通 UIKit 页面会自动检测,无需重复调用;SwiftUI 可在 onAppear / onDisappear 中配对调用。
若页面切换不经过 viewDidAppear(例如 React Native 等 SPA 场景),可用 setPage 直接替换当前逻辑页面,无需与 leavePage 配对。该接口不依赖行为自动采集模块,调用后会立即上报一次 page_view(navigation_type 为 replace)。
Swift
Objective-C
TDEM.setPage("checkout") // 替换当前逻辑页面
TDEM.setPage("checkout", pageTitle: "结算页") // 同时指定页面标题
[TDEM setPage:@"checkout"]; // 替换当前逻辑页面
[TDEM setPage:@"checkout" pageTitle:@"结算页"]; // 同时指定页面标题

自定义事件与测量

Swift
Objective-C
TDEM.track("checkout_completed", tags: ["step": "pay"], properties: ["order_type": "subscription"])
TDEM.measure("api_latency", duration: 320, tags: ["api": "/pay"], properties: [:])
TDEM.startMeasure("checkout_render") // 开始计时
TDEM.endMeasure("checkout_render", tags: ["step": "pay"], properties: [:]) // 结束并上报
TDEM.captureException(error, tags: ["module": "payment"], properties: [:]) // 上报已捕获异常
TDEM.trackStruggle("dead_click", severity: .high, properties: ["element": "buy_btn"], tags: [:])
[TDEM trackWithName:@"checkout_completed" tags:@{ @"step": @"pay" } properties:@{ @"order_type": @"subscription" }];
[TDEM measureWithName:@"api_latency" duration:320 tags:@{ @"api": @"/pay" }];
[TDEM startMeasureWithName:@"checkout_render"]; // 开始计时
[TDEM endMeasureWithName:@"checkout_render" tags:@{ @"step": @"pay" }]; // 结束并上报
[TDEM captureExceptionWithError:error tags:@{ @"module": @"payment" }]; // 上报已捕获异常
[TDEM trackStruggleWithName:@"dead_click" severity:TDEMStruggleSeverityHigh properties:@{ @"element": @"buy_btn" }];

启动与生命周期控制

Swift
Objective-C
TDEM.endLaunch() // 手动结束启动(需先设 launch.manualEndEnabled = true)
TDEM.flush() // 立即冲刷缓冲事件
TDEM.stop() // 停止 SDK
[TDEM endLaunch]; // 手动结束启动,返回 BOOL(需先设 launch.manualEndEnabled = true)
[TDEM flush]; // 立即冲刷缓冲事件
[TDEM stop]; // 停止 SDK
以上接口均需在 SDK 初始化 之后调用。未调用 TDEM.start 之前调用无效(返回 notRunning);若在 SDK 启动过程中调用,则会被缓冲排队,待就绪后按调用顺序上报。TDEM.setUser / setDeviceId / setTags 等上下文设置在启动前调用会先记录,同样在就绪后自动应用。

隐私标记

通过 TDEMPrivacyMetadata 主动声明某个控件为敏感,用于自动识别覆盖不到的场景(例如订单金额、收货地址这类字符串本身无语义特征的文案)。
Swift
Objective-C
import TDEMiOSSDK

// 标记为敏感:行为监控不采集该控件文本,Session Replay 遮罩该控件及其子树
TDEMPrivacyMetadata.setSensitive(true, for: orderAmountLabel)
TDEMPrivacyMetadata.setSensitive(false, for: orderAmountLabel) // 取消标记

// 只调 Session Replay 遮罩,不影响文本采集
TDEMPrivacyMetadata.setReplayMasking(.masked, for: qrCodeView)
TDEMPrivacyMetadata.setReplayMasking(.unmasked, for: qrCodeView)
TDEMPrivacyMetadata.setReplayMasking(.inherit, for: qrCodeView) // 恢复默认判定
@import TDEMiOSSDK;

// 标记为敏感:行为监控不采集该控件文本,Session Replay 遮罩该控件及其子树
[TDEMPrivacyMetadata setSensitive:YES forView:orderAmountLabel];
[TDEMPrivacyMetadata setSensitive:NO forView:orderAmountLabel]; // 取消标记

// 只调 Session Replay 遮罩,不影响文本采集
[TDEMPrivacyMetadata setReplayMasking:TDEMReplayMaskingMasked forView:qrCodeView];
[TDEMPrivacyMetadata setReplayMasking:TDEMReplayMaskingUnmasked forView:qrCodeView];
[TDEMPrivacyMetadata setReplayMasking:TDEMReplayMaskingInherit forView:qrCodeView]; // 恢复默认判定
TDEMReplayMasking 有三个取值:
.inherit:默认,按下面的遮罩判定链走。
.masked:强制遮罩。
.unmasked:显式不遮罩。
两条通道作用范围与继承语义不同:
通道
影响
对子控件是否继承
setSensitive
行为监控文本采集 + Session Replay 遮罩
行为监控不继承,Session Replay 继承
setReplayMasking
仅 Session Replay 遮罩
不继承
标记父容器时:Session Replay 会把标记向下传递,等价于遮罩整棵子树;但行为监控只判定被标记的那个控件本身,子控件文本仍会被采集,需逐个标记。
Session Replay 的遮罩判定按下列次序,命中即返回:
1. 不安全视图(类名含 camera / avplayerview):整帧跳过,不生成该帧回放。
2. 强制遮罩(forceMask):最高优先级,不可被任何标记撤销:setSensitive(true)(含父容器继承)、isSecureTextEntry、类名含 password / payment / authentication / safari / webview,以及 UITextField / UITextView 文本输入控件。
3. setReplayMasking(.masked) → 遮罩。
4. setReplayMasking(.unmasked) → 不遮罩。
5. maskAllText / maskAllImages 命中 → 遮罩。
因此对已标记敏感的控件调用 setReplayMasking(.unmasked) 不会放开遮罩。
与 Android 不同,iOS 没有 sentry-mask / sentry-unmask Tag 机制,也没有 unmaskViewClasses / maskViewClasses 配置项;强制遮罩来源为上述内置规则与业务标记。

行为元数据

TDEMBehaviorMetadata 用于在自动识别拿不到稳定标识时,手动指定页面 ID、控件 ID,或把某个页面、控件整体排除在行为监控之外。该能力为 iOS 独有。
Swift
Objective-C
import TDEMiOSSDK

// 为页面显式指定 page_id(默认取控制器的完全限定类名)
TDEMBehaviorMetadata.setPageID("checkout", for: checkoutViewController)
TDEMBehaviorMetadata.setPageID(nil, for: checkoutViewController) // 撤销,回落自动识别

// 为控件显式指定 element_id(优先级高于 accessibilityIdentifier)
TDEMBehaviorMetadata.setElementID("buy_button", for: buyButton)
TDEMBehaviorMetadata.setElementID(nil, for: buyButton)

// 整个页面不产生行为事件(如隐私页面)
TDEMBehaviorMetadata.setIgnored(true, for: privacyViewController)

// 单个控件不产生行为事件
TDEMBehaviorMetadata.setIgnored(true, for: adBannerView)

// 点击仍上报,但不参与 dead_click(无响应点击)判定
TDEMBehaviorMetadata.setDeadClickIgnored(true, for: refreshButton)

// 标记业务反馈键,随 click / scroll 事件以 struggle_feedback_key 上报
TDEMBehaviorMetadata.setStruggleFeedbackKey("coupon_refresh", for: refreshButton)
@import TDEMiOSSDK;

// 为页面显式指定 page_id(默认取控制器的完全限定类名)
[TDEMBehaviorMetadata setPageID:@"checkout" forViewController:checkoutViewController];
[TDEMBehaviorMetadata setPageID:nil forViewController:checkoutViewController]; // 撤销,回落自动识别

// 为控件显式指定 element_id(优先级高于 accessibilityIdentifier)
[TDEMBehaviorMetadata setElementID:@"buy_button" forView:buyButton];
[TDEMBehaviorMetadata setElementID:nil forView:buyButton];

// 整个页面不产生行为事件(如隐私页面)
[TDEMBehaviorMetadata setIgnored:YES forViewController:privacyViewController];

// 单个控件不产生行为事件
[TDEMBehaviorMetadata setIgnored:YES forView:adBannerView];

// 点击仍上报,但不参与 dead_click(无响应点击)判定
[TDEMBehaviorMetadata setDeadClickIgnored:YES forView:refreshButton];

// 标记业务反馈键,随 click / scroll 事件以 struggle_feedback_key 上报
[TDEMBehaviorMetadata setStruggleFeedbackKey:@"coupon_refresh" forView:refreshButton];
控件标识的解析优先级由高到低:
来源
说明
显式指定
TDEMBehaviorMetadata.setElementID(_:for:)
无障碍标识
accessibilityIdentifier
列表项
UITableViewCell / UICollectionViewCell 的 table.<section>.<row>、collection.<section>.<item>
稳定路径
从根视图起的子视图索引路径
类名兜底
class:<类名>
约束如下:
传入的字符串会去掉首尾空白,空字符串等同撤销设置;超过256字节会被截断。
页面 ID 未显式指定时,默认取控制器的完全限定类名;SwiftUI 的 UIHostingController 在未设置元数据时不产生页面事件。
setIgnored 作用于页面时,该页面下的所有行为事件均不产生;作用于控件时只影响该控件本身。
setDeadClickIgnored 只把控件排除在 dead_click(无响应点击)判定之外,点击事件本身仍会上报,并带上 dead_click_ignored 属性。
setStruggleFeedbackKey 标记的键会随该控件的点击、滚动事件以 struggle_feedback_key 属性一并上报,便于在控制台把行为事件与业务反馈关联。

会话与初始化监听

TDEM.currentSessionId() 返回当前分析会话 ID,SDK 未进入运行态时返回 nil。
TDEM.addInitListener(_:) 注册启动结算监听,可以在 TDEM.start 之前调用;若注册时启动已完成,会立即用上次的结算结果回调一次。TDEM.removeInitListener(_:) 注销监听。
Swift
Objective-C
final class InitLogger: TDEMInitListener {
func onInitSettled(_ started: Bool, remoteConfig: TDEMRemoteConfigResult?) {
print("started=\\(started), sampleRate=\\(remoteConfig?.tdemSampleRate ?? -1)")
}
}

let logger = InitLogger()
TDEM.addInitListener(logger)
TDEM.removeInitListener(logger)

let sessionId = TDEM.currentSessionId()

// 判断调用结果
if case let .rejected(error) = TDEM.endLaunch() {
print(error.code, error.reason)
}
@interface InitLogger : NSObject <TDEMInitListener>
@end

@implementation InitLogger
- (void)onInitSettled:(BOOL)started remoteConfig:(TDEMRemoteConfigResult *)remoteConfig {
NSLog(@"started=%d, sampleRate=%f", started, remoteConfig.tdemSampleRate);
}
@end

InitLogger *logger = [InitLogger new];
[TDEM addInitListener:logger];
[TDEM removeInitListener:logger];

NSString *sessionId = [TDEM currentSessionId];
TDEMRemoteConfigResult 携带远端配置快照:
enabled:远端是否放开采集。
tdemSampleRate:采样率。
replaySampleRate:回放采样率,可能为 nil。
需要判断调用结果时可参考 TDEMResult 与 TDEMError。TDEMResult 是 Swift 枚举(.accepted(eventID:) / .rejected(TDEMError)),Objective-C 不可见(OC 侧 endLaunch 直接返回 BOOL)。
TDEMErrorCode 取值与含义:
取值
含义
invalidConfiguration
初始化配置非法
configurationConflict
配置项之间相互冲突
notRunning
SDK 未处于运行态,调用被拒绝
invalidEvent
事件未通过校验
storageFailure
本地持久化失败,或启动期缓冲队列已满
internalFailure
SDK 内部错误

原始事件上报

TDEM.reportEvent(_:) 直接送入一条已成形的事件,用于 React Native 等薄桥接场景,SDK 不会对约定字段之外的字段做二次加工。
Swift
Objective-C
TDEM.reportEvent([
"eventType": "custom",
"eventCategory": "custom",
"timestamp": Int(Date().timeIntervalSince1970 * 1000),
"data": ["event_name": "my_event"]
])
[TDEM reportEvent:@{
@"eventType": @"custom",
@"eventCategory": @"custom",
@"timestamp": @([[NSDate date] timeIntervalSince1970] * 1000),
@"data": @{ @"event_name": @"my_event" }
}];
字段说明:
eventType / eventCategory:事件类型与分类,缺省均为 custom,也兼容下划线写法 event_type / event_category。
timestamp:事件发生时间(毫秒),缺省取当前时间。
data:事件负载,其中 event_name 用作事件名。
该接口仅在 SDK 运行态接受,未启动或已停止时调用会被拒绝(notRunning)。