XDSDK v7 iOS 快速接入指南
环境要求
- 国内最低 iOS 11.0,海外最低 iOS 15.0。
- XCode 26 或更高版本。
配置
XDSDK iOS 原生接入支持 SPM 和 framework 压缩包两种方式,推荐优先使用 SPM 接入。
通过 SPM 集成
- 在 Xcode 中打开项目,选择
File>Add Package Dependencies...。 - 在搜索框中填入 XDSDK SPM 仓库地址:
- 可以访问 GitHub 时使用:
https://github.com/xindong/XDSDK-SPM - 无法稳定访问 GitHub 时使用国内托管地址:
https://gitcode.com/XDSDK/XDSDK-SPM
- 可以访问 GitHub 时使用:
- 选择需要接入的版本,具体版本请以更新日志中的当前 XDSDK 版本为准。
- 在
Add to Target中选择游戏 App Target,并按需勾选需要的 Package Product。 - 准备
XDConfig.json参数文件,具体方式见下方参数文件。 - 在 App Target 中添加 SPM 提供的 Run Script Build Phases,用于复制 SDK 资源并根据
XDConfig.json自动配置Info.plist参数。
SPM 仓库内置了脚本用于自动完成部分 Xcode 配置,请直接从 SPM checkout 目录调用脚本,不需要复制脚本到游戏工程。
复制资源
在 App Target > Build Phases 中添加 Run Script Phase,命名为 Copy XDSDK Resources,用于复制 SDK bundle 资源:
SCRIPT_PATH="${BUILD_DIR%/Build/*}/SourcePackages/checkouts/XDSDK-SPM/Scripts/copy_xdsdk_resources.sh"
if [[ -f "$SCRIPT_PATH" ]]; then
bash "$SCRIPT_PATH"
else
echo "warning: XDSDK SPM resource script not found at $SCRIPT_PATH"
fi
请将该 Phase 放在 Build Phases 末尾(位于 Embed Frameworks / [CP] Embed Pods Frameworks 之后),取消勾选 Based on dependency analysis,并在 Build Settings 中将 User Script Sandboxing(ENABLE_USER_SCRIPT_SANDBOXING)设置为 NO。
自动配置 Info.plist
添加 Run Script Phase,命名为 Configure XDSDK Info.plist,用于读取 XDConfig.json 并自动写入 CFBundleURLTypes、LSApplicationQueriesSchemes 以及 Facebook 所需的顶层字段:
SCRIPT_PATH="${BUILD_DIR%/Build/*}/SourcePackages/checkouts/XDSDK-SPM/Scripts/configure_xdsdk_info_plist.py"
if [[ -f "$SCRIPT_PATH" ]]; then
/usr/bin/env python3 "$SCRIPT_PATH"
else
echo "warning: XDSDK SPM info-plist script not found at $SCRIPT_PATH"
fi
请将该 Phase 放在 Compile Sources 之前,取消勾选 Based on dependency analysis,并将 User Script Sandboxing 设置为 NO。脚本默认从 ${SRCROOT}/${PRODUCT_NAME}/XDConfig.json 读取配置;如果配置文件放在其他路径,请在 Run Script 环境变量中设置 XDSDK_CONFIG_PATH=/absolute/path/XDConfig.json。
使用 SPM 自动配置脚本后,如需调整脚本生成的配置,请修改 XDConfig.json,不要手动编辑对应的 Info.plist 字段。
GitHub 与 GitCode 托管的是同一套 XDSDK SPM 依赖,选择其中一个可稳定访问的地址即可。
通过 Framework 集成
- 请联系平台同事获取最新的 SDK 压缩包,解压后选择需要的 framework 和 bundle 导入到您的项目中。
- 压缩包分为
ThirdSDK和XDSDK两部分,所有的 framework 均为动态库,导入后请设置为Embed & Sign。
必选项:
- XDAccountSDK.framework(登录)
- XDPaymentSDK.framework(支付)
- XDCommonSDK.framework(基础库)
- XDTapSDK4WrapperSDK.framework(TapSDK 封装库)
- TapTapMomentResource.bundle(TapTap 资源包)
- TapTapLoginResource.bundle(TapTap 资源包)
- TapTapComplianceResource.bundle(TapTap 资源包)
- TapTapAchievementResource.bundle(TapTap 资源包)
可选项:
- XDCNWrapper.framework(国内三方 SDK,按需添加)
- XDGlobalWrapper.framework(海外三方 SDK,按需添加)
参数文件
将给到的参数配置文件名改为 XDConfig.json,导入到 XCode 工程中。
如果使用 Google 登录或 Firebase 埋点,请在 Firebase 后台下载 GoogleService-Info.plist 并添加到项目中。
添加系统依赖库
请检查项目中是否已自动添加以下依赖项:
LocalAuthentication.framework
AuthenticationServices.framework
SystemConfiguration.framework
Accelerate.framework
SafariServices.framework
Webkit.framework
CoreTelephony.framework
Security.framework
libc++.tdb
AVFoundation.framework
AdServices.framework
AdServices.framework需要在 Build Phases → Link Binary With Libraries 中设置为 Optional。AuthenticationServices.frameworkiOS 12 以上才支持,建议设置为 Optional。
配置编译选项
在 Build Setting 中的 Other Link Flag 中添加 -ObjC。
配置 URL Types 与 Schemes
如果通过 SPM 接入且已添加 Configure XDSDK Info.plist 脚本,CFBundleURLTypes、LSApplicationQueriesSchemes 等字段会由脚本根据 XDConfig.json 自动写入,无需手动维护。
通过 Framework 接入或未使用脚本时,需要手动配置 URL Types(详细内容请咨询平台同事),并在应用的 info.plist 中配置以下 LSApplicationQueriesSchemes:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>sinaweibo</string>
<string>weibosdk</string>
<string>weibosdk2.5</string>
<string>weibosdk3.3</string>
<string>mqqopensdkapiV2</string>
<string>mqq</string>
<string>mqqapi</string>
<string>tim</string>
<string>mqqopensdknopasteboard</string>
<string>weixin</string>
<string>weixinULAPI</string>
<string>weixinURLParamsAPI</string>
<string>tapsdk</string>
<string>tapiosdk</string>
<string>fbapi</string>
<string>fb-messenger-share-api</string>
<string>lineauth2</string>
<string>twitterauth</string>
<string>xhsdiscover</string>
<string>douyinopensdk</string>
<string>douyinliteopensdk</string>
<string>douyinsharesdk</string>
<string>snssdk1128</string>
<string>taptap</string>
<string>tiktokopensdk</string>
<string>tiktoksharesdk</string>
<string>snssdk1180</string>
<string>snssdk1233</string>
<string>instagram</string>
<string>kwai</string>
<string>kwaiAuth2</string>
<string>kwaiopenapi</string>
<string>KwaiBundleToken</string>
<string>kwai.clip.multi</string>
<string>KwaiSDKMediaV2</string>
<string>ksnebula</string>
</array>
配置权限列表
SDK 涉及到的权限请求如下:
| 权限说明 | 配置方式 | 备注 |
|---|---|---|
| 相机权限 | 在 info.plist 中配置 NSCameraUsageDescription 及描述文案。如:请允许 xxx 获取并使用您的相机。 | 客服页面可能需要拍摄相关照片或视频 |
| 麦克风权限 | 在 info.plist 中配置 NSMicrophoneUsageDescription 及描述文案。如:请允许 xxx 获取并使用您的麦克风。 | 客服页面可能需要拍摄相关视频 |
| 相册权限 | 在 info.plist 中配置 NSPhotoLibraryAddUsageDescription 及描述文案。如:请允许 xxx 获取并使用您的相册。 | 客服页面可能需要访问照片 |
配置 IDFA
如果您的应用需要打开 IDFA,则需要:
- 在
XDConfig.json中将idfa_enabled设置为true。 - 在应用中导入下列系统库:
AdSupport.framework
AppTrackingTransparency.framework -> 需要在 Build Phases - Link Binary With Libraries 中设置为 Optional - 在
info.plist中配置NSUserTrackingUsageDescription及对应的文案。
做完上述配置后应用会在您调用初始化时自动尝试请求获取 IDFA 权限,此时会弹出系统的隐私权限请求弹窗。
配置 App 所需能力
在 Capabilities 中按需打开 In-App Purchase、Push Notifications、Sign In With Apple 等功能。
配置 AppDelegate
在项目中实现了 UIApplicationDelegate 协议的类中引入头文件,并将系统回调转发给 SDK:
#import <XDCommonSDK/XDCommonSDK.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// ...其他初始化代码
[XDGSDK application:application didFinishLaunchingWithOptions:launchOptions];
return YES;
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[XDGSDK application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
[XDGSDK application:app openURL:url options:options];
return YES;
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
[XDGSDK application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
return YES;
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[XDGSDK application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
@end
请确保在 didFinishLaunchingWithOptions 中尽早调用 [XDGSDK application:application didFinishLaunchingWithOptions:launchOptions],其余回调方法也需要正确转发,否则可能影响登录、支付、推送等功能。
初始化
初始化SDK
- 请将初始化代码放在尽可能靠前的位置,在初始化成功前请不要绘制登录相关的界面。
- 如果初始化失败一般为配置问题,请根据错误信息检查配置是否正确或者咨询平台。
- 初始化成功前大部分接口都不可使用。
#import <XDCommonSDK/XDCommonSDK.h>
XDGInitParam *initParam = [XDGInitParam new];
// 语言和渠道根据实际情况设置
initParam.lang = XDGLanguageLocaleEnglish;
initParam.channel = @"AP";
// 可选:游戏自定义包体阶段参数,默认为空
initParam.gamePhase = @"release";
// db 参数可透传给 TapDB 的 device_login/user_login 事件
NSMutableDictionary *dbProperties = [NSMutableDictionary dictionary];
[dbProperties setValue:@"demo_extra_value" forKey:@"demo_extra_key"];
initParam.dbProperties = dbProperties;
[XDGSDK initSDK:initParam
handler:^(BOOL success, NSString *msg) {
if (success) {
NSLog(@"初始化成功");
} else {
NSLog(@"初始化失败:%@", msg);
}
}];
// 判断是否初始化完成
BOOL isInitialized = [XDGSDK isInitialized];
修改多语言
在初始化后可根据需要修改 SDK 语言。
#import <XDCommonSDK/XDCommonSDK.h>
/** 设置 SDK 显示语言
* @param locale 语言,在 XDGLanguageLocale 枚举中查看
*/
[XDGSDK setLanguage:XDGLanguageLocaleSimplifiedChinese];
登录
- 在初始化成功后可以进入登录页面但暂时先不要绘制登录按钮,先设置好用户状态回调并调用自动登录,如果自动登录失败再绘制登录按钮。
- 登录按钮点击后调用手动登录接口,需要传入对应的登录类型。登录失败后需要继续展示登录按钮让用户重新登录。
- 自动登录在每次打开游戏时只能触发一次,失败后只能调用手动登录接口。
- 收到用户退出登录的回调时需要回到登录页面并展示登录按钮。此时不要再调用自动登录接口。
状态回调
- 需要在初始化前设置好
typedef NS_ENUM(NSInteger, XDGUserStateChangeCode) {
XDGUserStateChangeCodeLogout = 0, // 用户登出
XDGUserStateChangeCodeBindSuccess = 1, // 用户绑定成功,msg = 登录类型字符串,例如:@"TAPTAP"
XDGUserStateChangeCodeUnBindSuccess = 2, // 用户解绑成功,msg = 登录类型字符串
XDGUserStateChangeCodeProtocolAgreedAfterLogout = 3, // 用户在登出后点击确认同意协议
XDGUserStateChangeCodeSupportNoUnread = 4, // 客服中心没有未读消息
XDGUserStateChangeCodeSupportHasUnread = 5, // 客服中心有未读消息
};
[XDGAccount addUserStatusChangeCallback:^(XDGUserStateChangeCode userStateChangeCode, NSString *message) {
if (userStateChangeCode == XDGUserStateChangeCodeBindSuccess) {
// 绑定新平台成功
} else if (userStateChangeCode == XDGUserStateChangeCodeUnBindSuccess) {
// 解绑平台成功
} else if (userStateChangeCode == XDGUserStateChangeCodeLogout) {
// 用户退出登录
} else if (userStateChangeCode == XDGUserStateChangeCodeProtocolAgreedAfterLogout) {
// 用户退出登录后点击同意协议
} else if (userStateChangeCode == XDGUserStateChangeCodeSupportNoUnread) {
// 客服中心没有未读消息
} else if (userStateChangeCode == XDGUserStateChangeCodeSupportHasUnread) {
// 客服中心有未读消息
}
}];
发起登录
LoginEntryTypeDefault (自动登录)
LoginEntryTypeTapTap
LoginEntryTypeApple
LoginEntryTypeGoogle
LoginEntryTypeFacebook
LoginEntryTypeLine
LoginEntryTypeTwitter
LoginEntryTypeSteam
LoginEntryTypeGuest
LoginEntryTypePhone
LoginEntryTypeEmail
LoginEntryType type = LoginEntryTypeDefault;
[XDGAccount loginByType:type loginHandler:^(XDGUser * _Nullable result, NSError * _Nullable error) {
if (error) {
// 登录失败
// error.code (错误码,用来区分类型)
// error.localizedDescription (可以用来展示给用户的错误原因文案)
} else {
// 登陆成功
NSString *xdUserID = result.userId; // result.userId 为用户在 XD 账户系统的 XD User ID(用户唯一标识)
NSString *name = result.name;
NSString *nickName = result.nickName;
NSString *avatar = result.avatar;
}
}];
用户中心
[XDGAccount openUserCenter];
退出登录
[XDGAccount logout];
账号注销
[XDGAccount openAccountDeletion];
打开客服
XDGRoleInfo *role = [XDGRoleInfo new];
role.roleId = roleId; // 必填
role.roleName = roleName; // 必填
role.serverId = serverId; // 必填
NSString *pathStr = @"客服内的相对路径,一般留空即可";
NSDictionary *paramsDic = @{@"自定义参数 key":@"自定义参数 value"};
[XDGAccount openCustomerService:role path:pathStr params:paramsDic];
个人信息页
仅限国内可使用
XDGRoleInfo *roleInfo = [XDGRoleInfo new];
roleInfo.roleId = roleId; // 必填
roleInfo.roleName = roleName; // 必填
roleInfo.roleLevel = roleLevel; // 必填
roleInfo.serverId = serverId; // 必填
[XDGAccount openUserDashboard:roleInfo];
内购
查询商品价格
- 在查询商品价格前请在后台配置好对应的商品信息。
- 使用 App Store 的商品 ID 进行查询。
NSArray *procudtIds = @[@"com.xd.sdkdemo1.stone30", @"com.xd.sdkdemo1.stone50"];
[XDGPayment queryWithProductIds:procudtIds completionHandler:^(NSArray<XDGProductInfo *> * _Nullable result, NSError * _Nullable error) {
if (error) {
NSLog(@"查询失败 %@", error);
} else {
for (XDGProductInfo *product in result) {
// 商品 ID
NSString *productId = product.productIdentifier;
// 展示价格(拼接好的完整货币符号和价格文本)
NSString *displayPrice = product.displayPrice;
}
}
}];
发起内购
XDGPaymentParams *params = [XDGPaymentParams new];
params.gameOrderId = @"可选,游戏侧订单号,不填会自动生成随机订单号";
params.productId = @"必须,在苹果后台配置的商品 ID";
params.roleId = @"必须,角色 ID";
params.serverId = @"必须,服务器 ID";
params.extra = @"可选,透传参数";
params.quantity = 1; // 购买数量,限制为 1-10
[XDGPayment payWithParams:params completionHandler:^(XDGOrderInfo * _Nullable orderInfo, NSError * _Nullable error) {
if (error) {
// 支付失败
} else {
// 支付成功
}
}];
查询 Apple 未消费订单
- 仅 Apple 平台可用。
- 查询到的订单可能是用户之前购买成功但未成功消费的订单,也可能是 App Store 中兑换的礼包码订单。
[XDGPayment queryPendingPurchases:^(NSArray<XDGPendingPurchase *> * _Nonnull result) {
for (XDGPendingPurchase *purchase in result) {
NSString *productId = purchase.productId; // 商品ID
NSString *purchaseToken = purchase.pendingPurchaseToken; // 订单标识符
}
}];
消费 Apple 未消费订单
XDGPaymentParams *params = [XDGPaymentParams new];
params.gameOrderId = @"可选,游戏侧订单号,不填会自动生成随机订单号";
params.productId = @"必须,在苹果后台配置的商品 ID";
params.roleId = @"必须,角色 ID";
params.serverId = @"必须,服务器 ID";
params.extra = @"可选,透传参数";
params.quantity = 1;
params.pendingPurchaseToken = @"未完成订单标识符,从查询未完成订单接口获取";
[XDGPayment handlePendingPurchase:params completionHandler:^(XDGOrderInfo * _Nullable orderInfo, NSError * _Nullable error) {
if (error) {
// 兑换或补单失败
} else {
// 兑换或补单成功
}
}];
工具
事件上报
#import <XDCommonSDK/XDCommonSDK.h>
/** 跟踪自定义事件
* @param eventName 事件名称
*/
NSString *eventName = @"custom_event_name";
[XDGSDK trackEvent:eventName];
/** 跟踪自定义事件
* @param eventName 事件名称
* @param properties 自定义属性
*/
NSString *eventName2 = @"custom_event_name";
NSMutableDictionary *properties = [NSMutableDictionary dictionary];
[XDGSDK trackEvent:eventName2 properties:properties];
// 跟踪角色信息
XDGRoleInfo *role = [XDGRoleInfo new];
role.roleId = @"your_role_id";
role.roleName = @"your_role_name";
role.roleLevel = 11;
role.serverId = @"your_server_id";
[XDGSDK trackRole:role];
商店评价
#import <XDCommonSDK/XDCommonSDK.h>
[XDGSDK storeReview];
打开网页
#import <XDCommonSDK/XDCommonSDK.h>
[XDGSDK openWebPageWithURL:@"https://活动页面地址" handler:^(XDGWebAction actionType, NSDictionary * _Nullable data) {
if (actionType == XDGWebActionCloseWeb) {
// 网页关闭
} else if (actionType == XDGWebActionMessage) {
// 网页透传消息
NSLog(@"网页透传消息 %@", data);
}
}];
公告
展示公告
展示公告 UI,由 SDK 处理公告的获取和展示。可以在公告后台进行样式自定义。
#import <XDCommonSDK/XDGAnnouncementManager.h>
XDGAnnouncementConfig *config = [XDGAnnouncementConfig new];
config.serverCode = @"1"; // 公告后台配置服务器后生成的代码
config.channel = @"ios"; // 渠道标识
[XDGAnnouncementManager openPageWithConfig:config handler:^(XDGWebAction actionType, NSDictionary * _Nullable data) {
if (actionType == XDGWebActionCloseWeb) {
// 页面关闭时回调
} else if (actionType == XDGWebActionMessage) {
// 页面消息回调
}
}];
检查未读公告
检查是否有未读公告,请不要频繁调用该接口,可能影响性能。
#import <XDCommonSDK/XDGAnnouncementManager.h>
XDGAnnouncementConfig *config = [XDGAnnouncementConfig new];
config.serverCode = @"1"; // 公告后台配置服务器后生成的代码
config.channel = @"ios"; // 渠道标识
[XDGAnnouncementManager requestUnreadWithConfig:config handler:^(_Bool hasRedDot) {
if (hasRedDot) {
// 有未读公告
} else {
// 无未读公告
}
}];
TapSDK
TapSDK 相关能力已由 XDSDK v7 统一封装。游戏侧不需要自行初始化 TapSDK,接入和接口说明请参考 TapSDK iOS 接口。