Treasure Data iOS SDK
iOS 和 tvOS SDK,用于Treasure Data。使用此 SDK,您可以轻松地将应用程序中的事件导入 Treasure Data。截至 0.9.0 版本,此 SDK 支持 iOS 12 及以上版本以及支持的 tvOS 12 及以上版本。
此外,还有一个用 Swift 编写的替代 SDK,可在 https://github.com/recruit-lifestyle/TreasureDataSDK 上找到。请注意,然而,它不支持主流 TD SDK 中的当前 GDPR 功能。
迁移到 1 版本
版本 1 有一些主要更改,与以前版本不兼容。如果您是从 0.9.0 或更早版本升级,您的代码将不会在没有以下步骤的情况下正确运行
- API 端点已更改为摄入端点。默认值是 https://us01.records.in.treasuredata.com。
initializeApiEndpoint:
API 现在不可用,请使用initializeWithApiKey:apiEndpoint:
代替。- 服务器端上传时间戳功能已删除。如果您需要此功能,请联系我们的支持团队。
uuid
现在是保留的列名。如果你尝试向事件的uuid
键添加值,你将不会在数据库中看到该列显示。
安装
有许多方法可以安装此库。
CocoaPods
CocoaPods 是设置 SDK 所必需的。如果您尚未安装,请首先进行安装。
$ gem install cocoapods
然后,在您的 Podfile 中添加以下行。
pod 'TreasureData-iOS-SDK', '= 1.0.1'
将此行添加到您的 Podfile 中(通常位于文件开头)。
use_frameworks!
最后,执行 'pod install'。
$ pod install
请记住,通过打开 .xcworkspace 文件而不是 .xcodeproj 文件来重新打开您的项目。
Swift Package Manager
您可以通过 Xcode 安装它:文件 > Swift Packages > 添加包依赖并输入 https://github.com/treasure-data/td-ios-sdk.git
。
或者将此行添加到 dependencies
数组中的 Package.swift 文件。
.package(url: "https://github.com/treasure-data/td-ios-sdk.git", .upToNextMajor(from: "1.0.1"))
框架
从 0.9.0 版本开始,我们不再支持独立的框架。
Objective-C 中的使用
- Treasure Data 指南(大部分内容与本README重叠)
- API 参考文档
导入 SDK 标准头文件
#import <TreasureData-iOS-SDK/TreasureData.h>
注册 TreasureData API 密钥
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[TreasureData initializeWithApiKey:@"your_api_key"];
}
我们建议使用 SDK 的只写 API 密钥。要获取一个,请
- 登录到 Treasure Data 控制台 http://console.treasuredata.com;
- 访问您的个人资料页面 http://console.treasuredata.com/users/current;
- 在“API 密钥”面板下输入您的密码;
- 在面板的下方,在“只写 API 密钥”部分,可以复制 API 密钥或点击“生成新的”并复制新的 API 密钥。
将事件添加到本地缓冲区
要将事件添加到本地缓冲区,您可以通过调用 TreasureData 的 addEvent
或 addEventWithCallback
API 实现。
- (IBAction)clickButton:(id)sender {
[[TreasureData sharedInstance] addEventWithCallback:@{
@"name": @"boo bar",
@"age": @42,
@"comment": @"hello world"
}
database:@"testdb"
table:@"demotbl"
onSuccess:^(){
NSLog(@"addEvent: success");
}
onError:^(NSString* errorCode, NSString* message) {
NSLog(@"addEvent: error. errorCode=%@, message=%@", errorCode, message);
}];
// Or, simply...
// [[TreasureData sharedInstance] addEvent:@{
// @"name": @"boo bar",
// @"age": @42,
// @"comment": @"hello world"
// }
// database:@"testdb"
// table:@"demotbl"];
指定您想要导入事件的数据库和表。数据库和表的总长度必须小于 129 个字符。每个表都将缓存不超过 10000 个事件。
此外,事件中的键长度不得超过 256 个字符,并且值长度不得超过 10000 个字符。
上传缓冲事件到TreasureData
要将缓冲事件上传到Treasure Data,您可以调用Treasure Data的uploadEvents
或uploadEventsWithCallback
API。
- (void)applicationDidEnterBackground:(UIApplication *)application {
__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// You can call this API to uplaod buffered events whenever you want.
[[TreasureData sharedInstance] uploadEventsWithCallback:^() {
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
onError:^(NSString *code, NSString *msg) {
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
];
// Or, simply...
// [[TreasureData sharedInstance] uploadEvents];
上传缓冲事件的时间取决于您应用的特性,但以下时机至少是上传的好时机。
- 当前屏幕关闭或切换到后台时
- 关闭应用程序时
发送的事件将在缓冲几分钟后才被导入到Treasure Data存储中。
在tvOS中,缓存存储位于缓存目录中,随时可能被清除。强烈建议尽可能频繁地调用上传事件API,以防止数据丢失。
重试上传和去重
此SDK通过结合以下功能以完全一次风格导入事件。
- 此SDK通过添加唯一键和重试来保留缓冲事件,直到确认事件已上传并存储在服务器端(至少一次)。
- 默认情况下,服务器端会记住过去1小时内所有事件的唯一键,以防止重复导入(最多一次)。
由于去重窗口默认为1小时,因此不要保留超过1小时的缓冲事件,以避免重复事件。
默认值
如果您想将事件添加到表、数据库或任何表或数据库,并自动为密钥设置值,请设置默认值。如果您为同一密钥设置了多个默认值,则新添加的事件将应用默认值并按以下顺序覆盖
- 首先应用针对所有表和数据库的默认值。
- 然后应用针对数据库中所有表的默认值。
- 接下来应用针对添加事件的表的默认值。
- 之后应用针对添加事件表和数据库的默认值。
- 最后,如果事件有该键的值,则该值将覆盖所有默认值。
设置默认值
[[TreasureData sharedInstance] setDefaultValue:@"Value" forKey:@"key" database:nil table:nil]; // Targeting all databases and tables
[[TreasureData sharedInstance] setDefaultValue:@"Value" forKey:@"key" database:"database_name" table:nil]; // Targeting all tables of database "database_name"
[[TreasureData sharedInstance] setDefaultValue:@"Value" forKey:@"key" database:nil table:"table_name"]; // Targeting all tables with "table_name"
[[TreasureData sharedInstance] setDefaultValue:@"Value" forKey:@"key" database:"database_name" table:"table_name"]; // Targeting table "table_name" of database "database_name"
获取默认值
NSString *defaultValue = [[TreasureData sharedInstance] defaultValueForKey:@"key" database:"database_name" table:"table_name"]; // Get default value for key targeting database "database_name" and table "table_name".
删除默认值
[[TreasureData sharedInstance] removeDefaultValueForKey:@"key" database:"database_name" table:"table_name"]; // Only remove default values targeting database "database_name" and table "table_name".
开始/结束会话
调用 startSession
方法时,SDK 会生成一个会话 ID,直到调用 endSession
。会话 ID 以列名 "td_session_id" 输出。同时,startSession
和 endSession
方法会添加一个包含 {"td_session_event":"start" 或 "end"}
的事件。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[TreasureData initializeWithApiKey:@"your_api_key"];
[[TreasureData sharedInstance] setDefaultDatabase:@"testdb"];
[[TreasureData sharedInstance] startSession:@"demotbl"];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[[TreasureData sharedInstance] endSession:@"demotbl"];
__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
[[TreasureData sharedInstance] uploadEventsWithCallback:^() {
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
onError:^(NSString *code, NSString *msg) {
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
// Outputs =>>
// [{"td_session_id":"cad88260-67b4-0242-1329-2650772a66b1",
// "td_session_event":"start", "time":1418880000},
//
// {"td_session_id":"cad88260-67b4-0242-1329-2650772a66b1",
// "td_session_event":"end", "time":1418880123}
// ]
];
如果你想处理以下情况,请使用一对类方法 startSession
和 endSession
进行全局会话跟踪
- 用户打开应用程序并使用
startSession
启动会话跟踪。让我们称这个会话为会话#0 - 用户切换到主屏幕并使用
endSession
结束会话 - 用户重新打开应用程序并在默认的 10 秒内重新启动会话跟踪。但你想将这个新会话视为与会话#0 相同的会话
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[TreasureData startSession];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[TreasureData endSession];
}
在这种情况下,你可以使用 getSessionId
类方法获取当前会话 ID
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[TreasureData startSession];
NSLog(@"Session ID=%@", [TreasureData getSessionId]);
}
检测是否为首次运行
您可以使用 isFirstRun
方法轻松检测是否为首次运行,然后使用 clearFirstRun
清除标志。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
:
if ([[TreasureData sharedInstance] isFirstRun]) {
[[TreasureData sharedInstance] addEventWithCallback:@{ @"event": @"installed" }
database:@"testdb"
table:@"demotbl"
onSuccess:^(){
[[TreasureData sharedInstance] uploadEventsWithCallback:^() {
[[TreasureData sharedInstance] clearFirstRun];
}
onError:^(NSString* errorCode, NSString* message) {
NSLog(@"uploadEvents: error. errorCode=%@, message=%@", errorCode, message);
}
];
}
onError:^(NSString* errorCode, NSString* message) {
NSLog(@"addEvent: error. errorCode=%@, message=%@", errorCode, message);
}];
}
关于错误代码
addEventWithCallback
和 uploadEventsWithCallback
方法将带有一个 errorCode
参数的 onError
块。这个参数对于了解错误的原因类型很有用。以下是以下错误代码。
init_error
: 初始化失败。invalid_param
: 传递给 API 的参数无效invalid_event
: 事件无效data_conversion
:数据转换为JSON格式失败storage_error
:在存储中读取/写入数据失败network_error
:由于网络问题,无法与服务器通信server_response
:服务器返回了错误响应
附加配置
端点
API端点(默认:https://us01.records.in.treasuredata.com)可以使用+[TreasureData initializeWithApiKey:apiEndpoint]
指定
[TreasureData initializeWithApiKey:@"your_api_key" apiEndpoint: @"https://specifying-another-endpoint.com"];
加密密钥
如果您已通过initializeEncryptionKey
类方法设置了加密密钥,我们的SDK在调用addEvent
或addEventWithCallback
方法时会将事件数据以加密形式保存。
[TreasureData initializeEncryptionKey:@"hello world"];
[[TreasureData sharedInstance] addEventWithCallback: ....];
默认数据库
[[TreasureData sharedInstance] setDefaultDatabase:@"testdb"];
[[TreasureData sharedInstance] addEventWithCallback:@{ @"event": @"clicked" } table:@"demotbl"]
自动将设备的UUID添加到每个事件中
如果您调用enableAutoAppendUniqId
,将自动将设备的UUID添加到每个事件中。此值在应用卸载或调用resetUniqId
之前不会更改。
[[TreasureData sharedInstance] enableAutoAppendUniqId];
它将值输出为列名td_uuid
。
获取UUID和重置UUID
您可以使用以下API在任何时间获取当前UUID(td_uuid
)。请注意,如果调用resetUniqId
,则此UUID将更改。
NSString *td_uuid = [[TreasureData sharedInstance] getUUID];
您也可以使用以下API在任何时间重置UUID(td_uuid
)。
[[TreasureData sharedInstance] resetUniqId];
自动将本地时间添加到每个事件记录中(默认启用)
默认情况下,本地时间戳将自动添加到事件的time
键中。如果您不添加time
键到事件中,而是使用disableAutoAppendLocalTimestamp
,服务器将添加服务器端时间戳到time
列。您还可以通过自定义列自动跟踪本地时间。如果是这样,则time
列将具有服务器端时间戳。
// Use local time as `time` column
[[TreasureData sharedInstance] enableAutoAppendLocalTimestamp];
// Add local time as a customized column name
[[TreasureData sharedInstance] enableAutoAppendLocalTimestamp:@"clientside_time"];
// Disable auto append local time
[[TreasureData sharedInstance] disableAutoAppendLocalTimestamp];
自动将UUID添加到每个事件记录中
如果您调用 enableAutoAppendRecordUUID
,则UUID将自动添加到每个事件记录中。每个事件都有一个不同的UUID。
[[TreasureData sharedInstance] enableAutoAppendRecordUUID];
// If you want to customize the column name, pass it to the API
[[TreasureData sharedInstance] enableAutoAppendRecordUUID:@"my_record_uuid"];
默认情况下,它将值输出为列名 record_uuid
。
自动将广告ID添加到每个事件记录中
如果您调用 enableAutoAppendAdvertisingIdentifier
,则广告ID将自动添加到每个事件记录中。
为了使此功能正常运行,您必须在“链接库”构建阶段链接Ad Support框架。用户也必须在他们的iOS设备上不开启“限制广告跟踪”功能,否则Treasure Data会将填充零的字符串作为广告ID(从Ad Support框架获得的值)发送。
从iOS 14开始,您必须使用AppTrackingTransparency框架明确请求用户对广告标识符的授权。有关如何在AppTrackingTransparency上实现这一要求,请参阅Apple官方文档。
如果您启用此功能,请注意您提交应用程序进行App Store审核时,必须声明获取广告标识符的正确原因。
[[TreasureData sharedInstance] enableAutoAppendAdvertisingIdentifier];
// If you want to customize the column name, pass it to the API
[[TreasureData sharedInstance] enableAutoAppendAdvertisingIdentifier:@"custom_ad_id_column"];
默认情况下,它以列名 td_maid
输出值。
自动将设备型号信息添加到每个事件中
如果您调用 enableAutoAppendModelInformation
,则设备型号信息将自动添加到每个事件中。
[[TreasureData sharedInstance] enableAutoAppendModelInformation];
它输出以下列名和值:
td_device
: UIDevice.modeltd_model
: UIDevice.modeltd_os_ver
: UIDevice.model.systemVersiontd_os_type
: "iOS"
自动将应用程序版本信息添加到每个事件中
如果您调用 enableAutoAppendAppInformation
,则应用程序版本信息将自动添加到每个事件中。
[[TreasureData sharedInstance] enableAutoAppendAppInformation];
它输出以下列名和值:
td_app_ver
: 核心基金键CFBundleShortVersionString
td_app_ver_num
: 核心基金键CFBundleVersion
自动向每个事件添加区域配置信息
如果调用 enableAutoAppendLocaleInformation
,将自动将区域配置信息添加到每个事件中。
[[TreasureData sharedInstance] enableAutoAppendLocaleInformation];
它输出以下列名和值:
td_locale_country
:[[NSLocale currentLocale] objectForKey: NSLocaleCountryCode]
td_locale_lang
:[[NSLocale currentLocale] objectForKey: NSLocaleLanguageCode]
使用服务器端上传时间戳
如果只想使用服务器端上传时间戳(而不是客户端记录的 addEvent
调用时的设备时间),请使用 enableServerSideUploadTimestamp
。
// Use server side upload time as `time` column
[[TreasureData sharedInstance] enableServerSideUploadTimestamp];
// Add server side upload time as a customized column name
[[TreasureData sharedInstance] enableServerSideUploadTimestamp:@"server_upload_time"];
启用/禁用调试日志
[TreasureData enableLogging];
[TreasureData disableLogging];
自动跟踪的事件
请注意,所有这些默认都是 *禁用的,您必须分别为每个类别明确启用它。
应用生命周期事件
可以通过以下方式启用
[[TreasureData sharedInstance] enableAppLifecycleEvent];
有三种类型的应用生命周期事件被追踪:TD_IOS_APP_OPEN
、TD_IOS_APP_INSTALL
和TD_IOS_APP_UPDATE
(写入到td_ios_event
列)。
追踪安装事件的示例
"td_ios_event" = "TD_IOS_APP_INSTALL";
"td_app_ver" = "1.1";
"td_app_ver_num" = 2;
应用内购买事件
TreasureData SDK能够自动追踪IAP SKPaymentTransactionStatePurchased
事件,无需编写自己的事务观测器。
[[TreasureData sharedInstance] enableInAppPurchaseEvent];
默认情况下是禁用的。这与appLifecycleEvent
、customEvent
有所不同。其他两个,由于历史原因,是持久设置,意味着它们的状态将保存跨应用启动。inAppPurchaseEvent
的行为像一个普通对象选项,并不会保存。您必须在初始化新的TreasureData
实例(可能是带有initializeWithApiKey
的sharedInstance
)之后启用它。
IAP事件的示例
"td_ios_event": "TD_IOS_IN_APP_PURCHASE",
"td_iap_transaction_identifier": "1000000514091400",
"td_iap_transaction_date": "2019-03-28T08:44:12+07:00",
"td_iap_quantity": 1,
"td_iap_product_identifier": "com.yourcompany.yourapp.yourproduct", ,
"td_iap_product_price": 0.99,
"td_iap_product_localized_title": "Your Product Title",
"td_iap_product_localized_description": "Your Product Description",
"td_iap_product_currency_code": "USD", // this is only available on iOS 10 and above
我们将做一个独立的SKProductsRequest
来获取完整的产品信息。如果请求失败,带有"td_iap_product_"前缀的字段将变为null。另外,请注意,currency_code
仅从iOS 10开始可用。
配置文件API
fetchUserSegments
此功能默认情况下未在账户上启用,请联系支持以获取更多信息。重要!您必须设置TreasureData的sharedInstance
的cdpEndpoint属性。使用示例
// Set cdpEndpoint when initialize TreasureData
[[TreasureData sharedInstance] setCdpEnpoint: @"[your cdp endpoint goes here]"]
// Call fetchUserSegments to get user segments as NSArray
NSArray *audienceTokens = @[@"Your Profile API (Audience) Token here"];
NSDictionary *keys = @{@"your_key": @"your_value"};
NSDictionary<TDRequestOptionsKey, id> *options = @{
TDRequestOptionsTimeoutIntervalKey: [NSNumber numberWithInteger: 10],
TDRequestOptionsCachePolicyKey: [NSNumber numberWithUnsignedInteger: NSURLRequestReloadIgnoringCacheData]
};
[[TreasureData sharedInstance] fetchUserSegments:audienceTokens
keys:keys
options:options
completionHandler:^(NSArray * _Nullable jsonResponse, NSError * _Nullable error) {
NSLog(@"fetchUserSegments jsonResponse: %@", jsonResponse);
NSLog(@"fetchUserSegments error: %@", error);
}];
GDPR 合规性
此 SDK 提供了一些方便的方法,可以轻松地关闭对设备的跟踪,无需使用大量的嵌套 if-else 语句。
// Opt-out of your own events
[[TreasureData sharedInstance] disableCustomEvent];
// Opt-out of TD generated events
[[TreasureData sharedInstance] disableAppLifecycleEvent];
[[TreasureData sharedInstance] disableInAppPurchaseEvent];
可以通过调用 enableCustomEvent
或 enableAppLifecycleEvent
来选择重新开启这些功能。请注意,这些设置会被持久化保存,因此即使在应用程序启动之间也仍然有效。通常,应在这些方法被调用以反映用户的选择时调用,而不是在每次初始化 SDK 时。默认情况下,自定义事件是启用的,而应用程序生命周期的事件是禁用的。
- 使用
resetUniqId
重置设备在后续事件中的标识。将td_uuid
随机化为另一个值,并通过额外的具有以下内容的{"td_ios_event": "forget_device_id", "td_uuid": <old_uuid>}
事件发送到defaultTable
。
tvOS
该 SDK 支持苹果 tvOS 12 及以上版本。API 和其行为与在 iOS 应用程序中使用的大致相同,除了
! 在 tvOS 中,缓存存储存储在缓存目录中,可以随时清除。强烈建议尽可能频繁地调用上传事件 API,以防止数据丢失。
故障排除
启用“数据保护”功能后,TD iOS SDK 偶尔会崩溃
- 如果您的应用在
UIApplicationDelegate applicationDidEnterBackground
中调用 SDK 的 API,例如TreasureData#endSession
,请检查是否在 iOS 锁定几秒后调用 SDK 的 API。如果是这样,请将耗时要长且在 SDK 的 API 运行之前在后台调用的其他任务。
- (void)applicationWillResignActive:(UIApplication *)application
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Some tasks that can take more than 10 seconds.
});
}
Swift 使用示例
详细请参考此示例项目(https://github.com/treasure-data/td-ios-sdk/tree/master/TreasureDataExampleSwift)。
Xcode 兼容性
当前版本使用 XCode v10.2 编译和测试。