推送排障
推送问题按“设备能否拿到 token → 服务端是否登记 → 服务端能否投递 → 客户端是否展示”四段排查,不要从客户端 UI 开始猜。
排查顺序
| 阶段 | 检查 | 常见结论 |
|---|---|---|
| 1. 权限 | 「设置 → 通知 → App」是否允许;首次弹窗是否点过允许 | 权限被拒:所有推送都不展示 |
| 2. token | `didRegisterForRemoteNotificationsWithDeviceToken` 是否有回调 | 无回调:Capability / provisioning / 网络问题 |
| 3. 登记 | `getPushTokens` 是否能看到该设备 token 且 active=true | 未登记或已失效:服务端不会投递 |
| 4. 投递 | 服务端 APNs 凭据、环境(sandbox / production)、bundle id | 环境错配:token 有效但投递失败 |
| 5. 展示 | 前台 `willPresent` 选项、免打扰、专注模式、通知摘要 | 已送达但被策略静默 |
| 6. 点击 | payload 是否带 conversationType / targetId | 点击无跳转:payload 缺字段 |
高频问题
| 现象 | 原因 | 处理 |
|---|---|---|
| Debug 包收不到、TestFlight 正常(或相反) | sandbox / production 环境不匹配 | 服务端按构建类型选择 APNs 主机与凭据 |
| 换账号后收到上一个账号的推送 | 退出时未注销 token | 退出登录调用 `unregisterPushToken` |
| 重装后收不到 | deviceToken 变化,旧 token 已失效 | 启动时重新登记;服务端按换绑置旧 token 失效 |
| 只有部分设备收不到 | 该设备权限关闭 / 专注模式 / 低电量模式 | 引导检查系统设置;不要用重装解决 |
| 推送到了但 App 内没有未读 | 只信了推送计数,未走 IMLib 补收 | 进入前台后重连并拉会话列表,以 SDK 数据为准 |
| 点击通知进错会话 | payload 缺 targetId / conversationType | 服务端补全 payload 字段 |
日志与验证
Shell
# 1) 查看设备日志中的 APNs 注册结果(连接真机)
log stream --device --predicate 'subsystem == "com.apple.UserNotifications"' --level debug
# 2) 服务端侧确认 token 台账与投递结果
# - 查询该用户活跃 token
# - 查看 APNs 返回的 status / reason(BadDeviceToken、Unregistered、DeviceTokenNotForTopic)
# 3) 用测试推送验证通道(服务端能力,不依赖业务消息)
# 向指定 deviceToken 发送一条测试通知,确认设备可收到先分离“通道”和“业务”
用一条测试推送确认 APNs 通道正常,再排查业务消息触发的推送;两者混在一起排查会浪费大量时间。