iOS

最近更新时间:2026-05-29 17:12:01

我的收藏
本文将介绍如何在 iOS 工程中集成 TIMPush。

前提条件

请确认已完成 iOS 厂商配置,获取到了下列信息:
资源
获取位置
用途
SDKAppID
腾讯云控制台 > 即时通信 IM > 推送服务 Push > 概览
调用 registerPush。创建 Push 应用后,腾讯云控制台会自动创建相同 SDKAppID 的 Chat 应用。
Push Key
腾讯云控制台 > 即时通信 IM > 推送服务 Push > 概览
独立 Push 场景作为 registerPushappKey 参数;Chat 场景 appKeynil。控制台展示名 AppKey
Chat Key
腾讯云控制台 > 即时通信 IM > Chat 应用详情
仅 Chat 登录使用。不要把 Chat Key 当作 registerPushappKey 传入。
证书 ID
腾讯云控制台上传 APNs 证书后生成
证书 ID 即 businessID,在 AppDelegate 中返回给 TIMPush。
App Group ID
Apple Developer Center / Xcode Capabilities
仅在需要推送触达统计时使用。
Push 服务开通状态
腾讯云控制台 > 即时通信 IM > 推送服务 Push > 概览
创建 Push 应用不等于已开通 Push 服务,请确认 Push 服务已开通。
TIMPush iOS VERSION
VERSION 是 Podfile 中 TIMPush 依赖的版本号占位符,例如 8.9.75378.8.73578.7.7201 等,请以实际接入版本为准。
本文示例中的 VERSIONSDKAppIDAppKeybusinessID、App Group ID 均为占位符,请勿在代码仓库中提交真实密钥。

集成 TIMPush

请按顺序完成本文配置。

主 App target 集成

TIMPush 通过 CocoaPods 集成。请在 Podfile 中为主 App target 添加 TIMPush 依赖。Podfile 示例:
target 'YourAppName' do
use_frameworks!
use_modular_headers!

pod 'TIMPush', 'VERSION'
end
如果您的工程已显式依赖 IMSDK,请保持 TIMPushTXIMSDK_Plus_iOS_XCFramework 版本一致,否则执行 pod install 时可能出现依赖冲突:
target 'YourAppName' do
use_frameworks!
use_modular_headers!

pod 'TXIMSDK_Plus_iOS_XCFramework', 'VERSION'
pod 'TIMPush', 'VERSION'
end
保存 Podfile 后,在工程目录执行:
pod install
如果无法安装 TIMPush 最新版本,可先执行 pod repo update 更新本地 CocoaPods 仓库列表后再 pod install。仓库更新可能耗时较长且影响依赖解析结果,建议在确认版本后执行。
验证pod install 输出 Installing TIMPush (VERSION),工程内可以 import TIMPush / #import <TIMPush/TIMPushManager.h> 且编译通过。

配置推送参数

配置 businessID

businessID 是腾讯云控制台上传 APNs 证书后生成的证书 ID。TIMPush 通过该 ID 识别当前 App 使用控制台中的哪一份 iOS 推送证书。
请在 AppDelegate 中实现 businessID 方法,并返回控制台生成的证书 ID。注意,Swift 端需要添加 @objc 标注。
Swift
Objective-C
// 在 AppDelegate.swift 中添加
import TIMPush

@objc func businessID() -> Int32 {
// TODO: Replace <#YOUR_BUSINESS_ID#> with the certificate ID generated in the Tencent Cloud console.
return <#YOUR_BUSINESS_ID#>
}
// 在 AppDelegate.m 中添加
#import <TIMPush/TIMPushManager.h>

- (int)businessID {
// TODO: Replace <#YOUR_BUSINESS_ID#> with the certificate ID generated in the Tencent Cloud console.
return <#YOUR_BUSINESS_ID#>;
}
如果 businessID 填写错误,部分 APNs 配置链路日志仍可能显示成功,因此还需要继续检查 token 上传和测试消息结果。
验证:在 businessID 方法内打 log,启动 App 后观察该方法是否被调用,且返回值与腾讯云控制台显示的证书 ID 一致。

配置 applicationGroupID(可选)

如果您需要统计推送触达率,需要配置 App Group ID,该 ID 应与您在厂商配置阶段准备的 App Group ID 保持一致。如果不需要推送触达统计,可以跳过本节。
Swift
Objective-C
// 在 AppDelegate.swift 中添加
import TIMPush

@objc func applicationGroupID() -> String {
// TODO: Replace <#YOUR_APP_GROUP_ID#> with the App Group ID configured in Apple Developer Center / Xcode.
return "group.<#YOUR_APP_GROUP_ID#>"
}
// 在 AppDelegate.m 中添加
#import <TIMPush/TIMPushManager.h>

- (NSString *)applicationGroupID {
// TODO: Replace <#YOUR_APP_GROUP_ID#> with the App Group ID configured in Apple Developer Center / Xcode.
return @"group.<#YOUR_APP_GROUP_ID#>";
}
验证:在 Apple Developer Center 和 Xcode 中确认主 App 与 Notification Service Extension 已绑定到同一个 App Group ID,且 AppDelegate 返回的 group.<#YOUR_APP_GROUP_ID#> 与之一致。

注册推送

registerPush 用于向 TIMPush 注册推送服务,并触发 APNs 设备 token 上传。每次 App 冷启动后,需要在合适时机调用一次。

接入场景与调用时机

TIMPush 支持三种接入场景,场景决定了推送标识、registerPush 调用时机以及 appKey 取值。
接入场景
适用说明
推送标识
调用时机
appKey 取值
Push
仅使用推送通知能力(如营销推送、活动通知),不接入 Chat。
registrationID:调用 registerPush 时由 SDK 生成的设备标识,卸载重装可能变化。
App 完成必要初始化、用户同意隐私政策并获得通知授权后调用 registerPush
Push Key
IM SDK + Push
同时集成 IM SDK + TIMPush。
userID:Chat 登录后 SDK 自动将推送标识切换为当前登录的 userID
IM SDK 登录成功回调中调用 registerPush
nil
TUIKit + Push
同时集成 TUIKit + TIMPush。
userID:Chat 登录后 SDK 自动将推送标识切换为当前登录的 userID。
建议在 TUILogin.login 成功回调中调用。
nil
警告:
Chat / TUIKit 场景下 registerPushappKey 必须传 nil,由 Chat 登录态接管推送标识。不要把 Push Key 或 Chat Key 当作 appKey 传入;同样不要在 Chat 登录前调用 registerPush,否则 token 可能上传失败,控制台排查工具显示「没有上传成功 token」。

调用 registerPush

请在用户同意隐私政策后再调用 registerPush。建议放在 AppDelegate 的初始化流程或业务侧统一的登录后回调中。按接入场景选择对应示例:
Push 场景
IM SDK + Push 场景
App 完成初始化、获得用户通知授权并具备 SDKAppID 和 Push Key 后调用 registerPushappKey 填 Push Key。
Swift
Objective-C
import TIMPush

func registerTIMPush() {
// TODO: Replace 0 with your SDKAppID.
let sdkAppID: Int32 = 0
// TODO: Replace "<#YOUR_PUSH_KEY#>" with your Push Key.
let appKey = "<#YOUR_PUSH_KEY#>"

TIMPushManager.registerPush(sdkAppID, appKey: appKey, succ: { deviceToken in
print(">>>>> TIMPush register success")
}, fail: { code, desc in
print(">>>>> TIMPush register failed, code:\\(code), desc:\\(desc)")
})
}
#import <TIMPush/TIMPushManager.h>

- (void)registerTIMPush {
// TODO: Replace 0 with your SDKAppID.
int sdkAppID = 0;
// TODO: Replace @"<#YOUR_PUSH_KEY#>" with your Push Key.
NSString *appKey = @"<#YOUR_PUSH_KEY#>";

[TIMPushManager registerPush:sdkAppID
appKey:appKey
succ:^(NSData * _Nonnull deviceToken) {
NSLog(@">>>>> TIMPush register success");
} fail:^(int code, NSString * _Nonnull desc) {
NSLog(@">>>>> TIMPush register failed, code:%d, desc:%@", code, desc);
}];
}
必须在 Chat 登录成功回调(或 TUILogin.login 成功回调)中调用 registerPush,且 appKey 必须传 nil
Swift
Objective-C
import TIMPush
import ImSDK_Plus

func loginIMAndRegisterPush() {
// TODO: Replace 0 with your SDKAppID.
let sdkAppID: Int32 = 0
let userID = "<#YOUR_USER_ID#>"
let userSig = "<#YOUR_USER_SIG#>"

V2TIMManager.sharedInstance().login(userID, userSig: userSig) {
// Chat login succeeded. Register TIMPush right after.
TIMPushManager.registerPush(sdkAppID, appKey: nil, succ: { deviceToken in
print(">>>>> TIMPush register success")
}, fail: { code, desc in
print(">>>>> TIMPush register failed, code:\\(code), desc:\\(desc)")
})
} fail: { code, msg in
print(">>>>> Chat login failed, code:\\(code), msg:\\(msg ?? "")")
}
}
#import <TIMPush/TIMPushManager.h>
#import <ImSDK_Plus/ImSDK_Plus.h>

- (void)loginIMAndRegisterPush {
// TODO: Replace 0 with your SDKAppID.
int sdkAppID = 0;
NSString *userID = @"<#YOUR_USER_ID#>";
NSString *userSig = @"<#YOUR_USER_SIG#>";

[[V2TIMManager sharedInstance] login:userID userSig:userSig succ:^{
// Chat login succeeded. Register TIMPush right after.
[TIMPushManager registerPush:sdkAppID
appKey:nil
succ:^(NSData * _Nonnull deviceToken) {
NSLog(@">>>>> TIMPush register success");
} fail:^(int code, NSString * _Nonnull desc) {
NSLog(@">>>>> TIMPush register failed, code:%d, desc:%@", code, desc);
}];
} fail:^(int code, NSString *msg) {
NSLog(@">>>>> Chat login failed, code:%d, msg:%@", code, msg);
}];
}
验证
1. registerPushsucc 回调被触发;登录腾讯云控制台 > 即时通信 IM > 推送服务 Push 排查工具,输入 registrationIDuserID,确认 token 已上传
2. 如触发 fail,可按 错误码 查询 code 含义。

registrationIDuserID 说明(可选读)

名称
含义
使用场景
registrationID
TIMPush 默认在调用 registerPush 时生成的设备推送标识,卸载重装后可能变化。
独立 Push 场景。控制台或服务端 REST API 可指定 registrationID 下发推送。
userID
Chat 登录时使用的业务用户 ID。
Chat / TUIKit 离线推送场景。Chat 登录成功后调用 registerPush(_, appKey: nil, ...),推送标识切换到当前 userID
getRegistrationID:
+ (void)getRegistrationID:(TIMPushValueCallback)callback,回调返回当前注册成功的推送 ID。
Chat 场景下回调返回 Chat 登录的 userID;独立 Push 场景下返回 SDK 生成的设备标识。控制台或服务端发送测试消息时,使用该值定位设备。
请在 registerPush 成功回调之后再调用 getRegistrationID:,否则可能拿不到值。
setRegistrationID:callback:
+ (void)setRegistrationID:(NSString *)registrationID callback:(TIMPushCallback)callback,自定义推送 ID 的接口,必须在 registerPush 之前调用。
混用场景中如需自定义 ID,自定义值必须与 Chat 登录使用的 userID 完全一致,否则可能产生账号互踢,导致推送不稳定。

配置消息触达统计(可选)

仅当您需要统计推送触达率时,才需要完成本节配置;如果只需要接收普通离线推送,可跳过本节。
完整流程包含:
1. 在 Xcode 中创建并配置 Notification Service Extension target
2. 确保 APNs payload 开启 mutable-content
3. 在 Extension 中调用 TIMPush 处理通知。

创建并配置 Notification Service Extension target

1. 在 Xcode 中选择 File > New > Target
2. 选择 Notification Service Extension
3. 输入 Extension 名称。
4. 创建完成后,确认工程中出现新的 Extension target。
5. 在 Extension target 的 Signing & Capabilities 中配置与主 App 相同的 App Groups。
6. Podfile 中为 Extension target 添加 TIMPush 依赖:
target 'YourNotificationServiceExtensionTarget' do
use_frameworks!
use_modular_headers!

pod 'TIMPush', 'VERSION'
end
7. 执行 pod install
注意:
Extension target 是独立 target,不能复用主 App target 的 Pod 依赖。若未在 Extension target 中添加 TIMPush,在 NotificationServiceimport TIMPush#import <TIMPush/TIMPushManager.h> 会失败。

开启 mutable-content

mutable-content 是 APNs payload 字段,由发送方在推送内容中设置。只有 payload 中开启 mutable-content,iOS 10 及以上系统才会在送达前调用 Notification Service Extension,触达统计才能生效。
请确保通过以下任一方式开启 mutable-content
腾讯云控制台推送:在控制台推送测试或发送页面,勾选 mutable-content 相关选项。
服务端 REST API:在 APNs payload 中设置 "mutable-content": 1
Chat SDK 发送:以 Chat SDK 离线推送配置文档为准。

在 Extension 中处理通知

请将 group.<#YOUR_APP_GROUP_ID#> 替换为您在 Apple Developer Center 和 Xcode 中配置的 App Group ID。主 App 和 Extension 必须使用同一个 App Group ID。以下 Swift 写法基于 OC 接口自动桥接,参数命名可能随 SDK 版本调整,请以 SDK 头文件 TIMPushManager.h 为准。
Swift
Objective-C
// 在 NotificationService.swift 中添加

import UserNotifications
import TIMPush

class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?

override func didReceive(
_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
) {
self.contentHandler = contentHandler
self.bestAttemptContent = request.content.mutableCopy() as? UNMutableNotificationContent

let appGroupID = "group.<#YOUR_APP_GROUP_ID#>"
TIMPushManager.handleNotificationServiceRequest(request: request, appGroupID: appGroupID) { [weak self] content in
guard let self = self else {
contentHandler(content)
return
}
self.bestAttemptContent = content.mutableCopy() as? UNMutableNotificationContent
contentHandler(self.bestAttemptContent ?? content)
}
}

override func serviceExtensionTimeWillExpire() {
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
// 在 NotificationService.m 中添加
#import "NotificationService.h"
#import <TIMPush/TIMPushManager.h>

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request
withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
NSString *appGroupID = @"group.<#YOUR_APP_GROUP_ID#>";

[TIMPushManager handleNotificationServiceRequest:request
appGroupID:appGroupID
callback:^(UNNotificationContent *content) {
contentHandler(content);
}];
}

@end
验证:发送一条带 mutable-content 的测试推送,在 didReceive 内打断点或 log 确认 Extension 被调用;后续在腾讯云控制台触达统计页面应能看到上报数据。

测试推送

完成上述集成步骤后,需要通过发送测试消息验证整体链路是否打通。发送消息前请确认:
1. App 已获得系统通知权限;
2. Xcode 主 App target 已开启 Push Notifications,AppDelegate 已正确返回 businessID
3. App 已置于后台或杀掉进程(前台时离线推送可能不触发)。
发送测试消息可以采用下面几种方法:
控制台发送
REST API 发送
SDK API 发送
仅集成 TIMPush 的用户,建议优先使用腾讯云控制台接入测试能力验证离线推送。
操作路径:腾讯云控制台 > 即时通信 IM > 推送服务 Push > 接入测试。在接入测试页面,可以指定 registrationIDuserID 发送离线推送测试。
验证:App 置于后台后发送测试消息,设备能收到离线推送通知。如果收不到,请参见下文「收不到推送排障流程」逐步排查。
如果需要通过服务端发送推送,可参考 REST API 接口 - 发起全员/标签推送
如果您的项目已接入 IMSDK,可在调用 sendMessage 发送消息时,通过 V2TIMOfflinePushInfo 设置离线推送参数,再交由 V2TIMManager 发送消息。具体方法签名以您接入的 IMSDK 版本头文件为准。
Swift
Objective-C
import ImSDK_Plus

let pushInfo = V2TIMOfflinePushInfo()
pushInfo.title = "推送标题"
pushInfo.desc = "推送内容"
pushInfo.ext = "{\\"action\\":\\"open_chat\\",\\"conversationID\\":\\"c2c_userA\\"}"

let message = V2TIMManager.sharedInstance().createTextMessage("Hello TIMPush")

V2TIMManager.sharedInstance().send(
message,
receiver: "<#TARGET_USER_ID#>",
groupID: nil,
priority: V2TIM_PRIORITY_DEFAULT,
onlineUserOnly: false,
offlinePushInfo: pushInfo,
progress: nil,
succ: { msg in
print(">>>>> sendMessage success, msgID = \\(msg?.msgID ?? "")")
},
fail: { code, desc in
print(">>>>> sendMessage failed, code:\\(code), desc:\\(desc ?? "")")
}
)
#import <ImSDK_Plus/ImSDK_Plus.h>

V2TIMOfflinePushInfo *pushInfo = [[V2TIMOfflinePushInfo alloc] init];
pushInfo.title = @"推送标题";
pushInfo.desc = @"推送内容";
pushInfo.ext = @"{\\"action\\":\\"open_chat\\",\\"conversationID\\":\\"c2c_userA\\"}";

V2TIMMessage *message = [[V2TIMManager sharedInstance] createTextMessage:@"Hello TIMPush"];

[[V2TIMManager sharedInstance] sendMessage:message
receiver:@"<#TARGET_USER_ID#>"
groupID:nil
priority:V2TIM_PRIORITY_DEFAULT
onlineUserOnly:NO
offlinePushInfo:pushInfo
progress:nil
succ:^{
NSLog(@">>>>> sendMessage success");
} fail:^(int code, NSString *desc) {
NSLog(@">>>>> sendMessage failed, code:%d, desc:%@", code, desc);
}];
sendMessage 属于 IMSDK 消息发送能力。仅集成 TIMPush 的用户不需要为了验证离线推送而额外接入完整 Chat 初始化、登录和消息发送流程。

处理通知点击跳转

通知点击跳转需要三步配合完成:控制台配置点击动作、发送推送时携带跳转参数、客户端注册监听并解析参数。三步缺一则跳转不生效。

配置控制台点击动作

在腾讯云控制台配置推送证书的「点击后续动作」,勾选「打开应用内指定页面」:
操作路径:腾讯云控制台 > 即时通信 IM > 推送服务 Push > 推送设置 > 厂商配置 > iOS > 对应 APNs 证书 > 编辑 > 点击后续动作 > 打开应用内指定页面。

发送推送时携带 ext

发送离线推送时,通过 ext 字段携带跳转所需的业务信息(如目标页面、会话 ID 等)。ext 是一个字符串,建议使用 JSON 格式便于客户端解析。
REST API 发送
SDK API 发送
通过 REST API 发送推送时,在请求体的 Ext 字段中设置 JSON 字符串:
{
"MsgBody": [],
"OfflinePushInfo": {
"PushFlag": 0,
"Title": "离线推送标题",
"Desc": "离线推送内容",
"Ext": "{\\"action\\":\\"open_chat\\",\\"conversationID\\":\\"c2c_userA\\"}"
}
}
控制台接入测试页面同样支持设置 Ext 字段,填入 JSON 字符串即可。
API 通过 V2TIMOfflinePushInfoext 属性携带跳转参数。
Swift
Objective-C
import ImSDK_Plus

let pushInfo = V2TIMOfflinePushInfo()
pushInfo.title = "推送标题"
pushInfo.desc = "推送内容"
pushInfo.ext = "{\\"action\\":\\"open_chat\\",\\"conversationID\\":\\"c2c_userA\\"}"
#import <ImSDK_Plus/ImSDK_Plus.h>

V2TIMOfflinePushInfo *pushInfo = [[V2TIMOfflinePushInfo alloc] init];
pushInfo.title = @"推送标题";
pushInfo.desc = @"推送内容";
pushInfo.ext = @"{\\"action\\":\\"open_chat\\",\\"conversationID\\":\\"c2c_userA\\"}";

客户端注册监听并解析 ext

请在 AppDelegate 中遵循 TIMPushListener 协议,调用 addPushListener: 注册监听器,并在 onNotificationClicked 中解析 ext。
Swift
Objective-C
// 在 AppDelegate.swift 中遵循 TIMPushListener 并注册 listener:

import UIKit
import TIMPush

@main
class AppDelegate: UIResponder, UIApplicationDelegate, TIMPushListener {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
TIMPushManager.addPushListener(listener: self)
return true
}

// MARK: - TIMPushListener
@objc func onNotificationClicked(_ ext: String) {
print(">>>>> TIMPush notification clicked, ext:\\(ext)")
// Parse ext and navigate to the target page.
}

@objc func onRecvPushMessage(_ message: TIMPushMessage) {
print(">>>>> TIMPush received push message")
}

@objc func onRevokePushMessage(_ messageID: String) {
print(">>>>> TIMPush revoked push message:\\(messageID)")
}
}
// 在 AppDelegate.h 中声明协议:
#import <TIMPush/TIMPushManager.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, TIMPushListener>
@end

// 在 AppDelegate.m 中注册 listener 并处理回调:

#import <TIMPush/TIMPushManager.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[TIMPushManager addPushListener:self];
return YES;
}

// MARK: - TIMPushListener
- (void)onNotificationClicked:(NSString *)ext {
NSLog(@">>>>> TIMPush notification clicked, ext:%@", ext);
// Parse ext and navigate to the target page.
}

- (void)onRecvPushMessage:(TIMPushMessage *)message {
NSLog(@">>>>> TIMPush received push message");
}

- (void)onRevokePushMessage:(NSString *)messageID {
NSLog(@">>>>> TIMPush revoked push message:%@", messageID);
}
onRecvPushMessage 回调中传入的 TIMPushMessage 对象提供以下字段,便于业务读取离线推送内容:
字段
类型
含义
title
NSString *
离线推送标题。
desc
NSString *
离线推送内容。
ext
NSString *
离线推送透传内容,业务自定义字段,常用于点击跳转。
messageID
NSString *
消息唯一标识 ID,可用于去重或 onRevokePushMessage 撤回匹配。

收不到推送排障流程

如果发送测试消息后设备没有收到推送,请按以下流程逐步排查。每一步确认通过后再进入下一步,可以快速定位问题所在环节。不要只凭单条 APNs 配置成功日志判断接入成功;运行 App 后可过滤 TIMPush 关键字观察整体日志。

步骤1:确认 APNs 权限和 Push Notifications 能力

App 是否已获得系统通知权限。
Xcode 主 App target 的 Signing & Capabilities 是否已开启 Push Notifications
Apple Developer Center 对应 App ID 的 Capabilities 是否已勾选 Push Notifications
通过后,进入第二步。

步骤2:确认 registerPush 是否成功

检查 registerPush 回调结果:
succ 已触发:注册成功,进入第三步。
fail 触发:注册失败。结合下文「错误码」表查询 code 含义,并按返回的 desc 排查 SDKAppIDappKey 取值(独立 Push 用 Push Key,Chat / TUIKit 用 nil)以及调用时机。

步骤3:确认控制台排查工具能查到 token

在腾讯云控制台 即时通信 IM > 推送服务 Push 的排查工具中输入 registrationIDuserID
能查到设备且 token 正常:进入第四步。
查不到设备 / 显示「没有上传成功 token」:常见原因是 Chat 场景未在 Chat 登录成功后调用 registerPush,或调用顺序错误。请重新核对调用时机。

步骤4:确认 businessID / Bundle ID / APNs 环境匹配

控制台显示「不允许向该主题推送」或仅部分设备能收到推送时,通常是这一层出了问题:
Xcode 主 App target 的 Bundle Identifier 是否与 Apple App ID 一致。
腾讯云控制台上传的 APNs 证书是否绑定同一个 Bundle ID。
AppDelegate 返回的 businessID 是否为该 Bundle ID 对应的证书 ID。
APNs 环境(开发 / 生产)是否与 App 安装包环境匹配。
p8 / p12 证书是否上传到正确应用。

步骤5:确认 Chat / TUIKit 场景登录顺序

仅 Chat / TUIKit 场景需要检查:
registerPush 是否在 Chat 登录成功回调(或 TUILogin.login 成功回调)之后调用。
appKey 参数是否传 nil,而不是 Push Key 或 Chat Key。
自定义 registrationID 是否与 Chat 登录使用的 userID 完全一致(不一致会产生账号互踢)。

步骤6:确认测试消息发送目标和设备状态

测试消息发送给的 registrationIDuserID 是否与 getRegistrationID: 返回值一致。
App 是否处于后台或已杀进程(前台时离线推送可能不触发)。
设备是否处于可接收通知状态(勿扰模式、通知权限等)。
推送服务是否到期(试用到期后自动停止服务)。

仍无法解决

如果按上述流程仍无法定位问题,请 联系我们 提交反馈。