iOS应用启动时无法生成FCM Token的技术咨询
关于iOS FCM远程通知获取Token的正确实现说明
你的实现方式是完全正确的,以下是针对你的疑问的详细解释:
1. FCM Token生成的核心逻辑
FCM的注册Token(fcmToken)生成依赖于苹果APNs的Device Token——FCM SDK需要拿到APNs Device Token后,才能与Firebase服务器交互生成对应的FCM Token。而UIApplication.shared.registerForRemoteNotifications()是iOS系统规定的、获取APNs Device Token的必要触发操作,只有调用这个方法,系统才会向APNs服务器请求Device Token,后续才能触发didRegisterForRemoteNotificationsWithDeviceToken代理,进而让FCM生成并返回fcmToken。
2. 关于“之前无需调用就能获取Token”的原因
你之前遇到的无需调用也能获取Token的情况,大概率是以下两种场景之一:
- 旧版FCM SDK行为差异:早期部分版本的FCM SDK可能在内部隐式触发了APNs注册流程,但后续版本为了严格遵循iOS系统规范,调整为需要开发者显式调用
registerForRemoteNotifications()。 - 缓存的旧Token:如果之前安装过该应用,设备上缓存了旧的APNs Device Token,FCM会直接复用缓存内容生成Token,导致你误以为无需调用注册方法,但当你清除应用缓存、重装应用或设备重置后,缓存失效就必须显式调用了。
3. 通知权限与APNs注册的区别
需要明确:registerForRemoteNotifications()和请求用户通知权限是两个独立的流程:
registerForRemoteNotifications()仅用于获取APNs Device Token,即使用户拒绝了通知推送权限,调用这个方法依然能拿到Device Token,FCM也能正常生成fcmToken——此时你依然可以通过FCM发送静默通知等不需要用户授权展示的推送类型。- 请求用户授权的方法是
UNUserNotificationCenter.current().requestAuthorization(options:),这才是弹出权限弹窗的操作,你可以根据业务需求选择合适的时机调用(比如用户进入特定页面后),但registerForRemoteNotifications()建议在应用启动时尽早调用,确保FCM Token能及时生成。
4. 代码优化建议
针对你当前的代码,可以做两点小优化:
- 避免重复调用注册方法,先检查当前注册状态:
private func attemptRegisterForNotification() { Messaging.messaging().delegate = self UNUserNotificationCenter.current().delegate = self if !UIApplication.shared.isRegisteredForRemoteNotifications { UIApplication.shared.registerForRemoteNotifications() } else { // 已注册,可尝试直接获取当前的FCM Token if let token = Messaging.messaging().fcmToken { print("已缓存的FCM Token: \(token)") } } }
- 移除无关代码:
Auth.auth().setAPNSToken(deviceToken, type: .unknown)这行代码仅用于Firebase Auth的APNs登录验证场景,如果你的应用没有使用该功能,可以直接删除,不影响FCM Token的生成。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

