React Native Firebase推送通知iOS真机不生效问题求助
React Native Firebase iOS 推送失效排查修复方案
你当前安卓端推送正常,仅iOS真机失效,核心问题基本集中在原生端配置缺失、JS逻辑时序问题、环境匹配错误三类,按下面步骤逐一排查修复即可:
1. 补全 AppDelegate.mm 缺失的核心原生代码
你贴出的AppDelegate.mm代码是不完整的,缺少iOS推送必须的APNs注册逻辑、token回传逻辑、前台推送回调,这是最常见的失效原因,按下面内容补全:
首先修改AppDelegate.h,引入依赖并签署对应协议:
#import <UIKit/UIKit.h> #import <React/RCTBridgeDelegate.h> // 👇 新增两个头文件引入 #import <UserNotifications/UserNotifications.h> #import <FirebaseMessaging/FirebaseMessaging.h> @interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificationCenterDelegate, FIRMessagingDelegate> @property (nonatomic, strong) UIWindow *window; @end
然后修改AppDelegate.mm,补全didFinishLaunchingWithOptions方法内逻辑,新增缺失的代理方法:
#import "AppDelegate.h" #import <React/RCTBridge.h> #import <React/RCTBundleURLProvider.h> #import <React/RCTRootView.h> #import "RNFBMessagingModule.h" #import <React/RCTAppSetupUtils.h> #import <Firebase.h> - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [FIRApp configure]; RCTAppSetupPrepareApp(application); // 👇 新增:注册APNs推送、设置通知中心代理 UNUserNotificationCenter *notiCenter = [UNUserNotificationCenter currentNotificationCenter]; notiCenter.delegate = self; [application registerForRemoteNotifications]; RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; NSDictionary *appProperties = [RNFBMessagingModule addCustomPropsToUserProps:nil withLaunchOptions:launchOptions]; // 你原本的根视图加载逻辑保留,不要删除 RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"你的项目名" initialProperties:appProperties]; // ... 剩下你原有的window、rootViewController配置逻辑不变 } // 👇 新增:APNs注册成功后将device token传给Firebase - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { [FIRMessaging messaging].APNSToken = deviceToken; } // 👇 新增:APNs注册失败时打印错误,方便排查 - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { NSLog(@"APNs 注册失败: %@", error.localizedDescription); } // 👇 新增:APP在前台时收到推送的回调,配置前台推送展示样式 - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler { NSDictionary *userInfo = notification.request.content.userInfo; [[FIRMessaging messaging] appDidReceiveMessage:userInfo]; // 前台收到推送时展示横幅、角标、播放声音,可按需调整 completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound); }
改完原生代码后,重新执行pod install再编译项目。
2. 检查环境与证书配置
- 确认Firebase控制台上传的APNs密钥正确:优先使用
.p8格式的通用密钥(同时支持开发、生产环境),如果用的是老版.p12证书,要保证证书环境和你当前的打包环境一致(Xcode直连真机调试用开发证书,TestFlight/Adhoc包用生产证书) - 确认苹果开发者后台对应App ID已经开启Push Notifications能力:不要只在Xcode里开能力开关,要登录苹果开发者后台,找到对应Bundle ID的App ID配置,确认Push Notifications项为启用状态,重新生成描述文件下载到Xcode
- 确认Bundle ID完全匹配:Firebase控制台添加的iOS应用Bundle ID,和Xcode项目General页签里的Bundle Identifier必须完全一致,大小写敏感
- 确认Xcode里的Background Modes勾选了
Remote notifications选项,不要漏选
3. 修正JS层逻辑问题
你当前的JS逻辑存在时序错误和token更新逻辑漏洞,按下面内容修改:
3.1 修正权限申请与注册的调用时序
不要在APP启动时直接调用注册方法,要等用户同意推送权限后再执行注册:
// app.js async function registerAppWithFCM() { if (!messaging().isDeviceRegisteredForRemoteMessages) { await messaging().registerDeviceForRemoteMessages(); } } const App: () => Node = () => { useEffect(()=>{ const initPushService = async () => { const authStatus = await messaging().requestPermission(); const enabled = authStatus === messaging.AuthorizationStatus.AUTHORIZED || authStatus === messaging.AuthorizationStatus.PROVISIONAL; if (enabled) { console.log('推送权限已授权,状态码:', authStatus); await registerAppWithFCM(); GetFCMToken(); NotificationListener(); // 监听token刷新事件 messaging().onTokenRefresh(async (newToken) => { await AsyncStorage.setItem("fcmToken", newToken); // 这里加你自己的逻辑:把新token上报给业务服务端 }) } } initPushService(); },[]) // 原有页面渲染逻辑保留 }
3.2 修正FCM Token获取逻辑
你当前的逻辑是本地存了token就永远不再获取,但是iOS重装APP、重置系统权限后token会变化,修改为:
async function GetFCMToken(){ try { const fcmToken = await messaging().getToken(); if(fcmToken){ console.log("当前FCM token:", fcmToken); const oldToken = await AsyncStorage.getItem("fcmToken"); if(oldToken !== fcmToken){ await AsyncStorage.setItem("fcmToken", fcmToken); // 这里加你自己的逻辑:把token上报给业务服务端 } } } catch (error) { console.log("获取FCM token失败:", error); } }
index.js里的后台消息处理逻辑不需要改,保持原样即可。
4. 测试注意事项
- iOS推送必须用真机测试,模拟器不支持APNs推送
- 首次安装APP弹出权限弹窗时必须选择允许,如果之前点了拒绝,要去iOS系统设置-对应APP的通知设置里手动开启权限
- 测试推送时,推送payload必须包含
notification字段,仅传data字段的静默推送在APP被杀死的状态下无法正常唤起展示 - Xcode直连真机调试时,Firebase控制台发推送要选择开发(沙盒)环境,打TestFlight/正式包要选生产环境,环境不匹配会收不到推送
- 如果之前在真机上装过旧版本APP,建议卸载后重新编译安装,避免旧的描述文件、缓存token影响测试
内容的提问来源于stack exchange,提问作者ttars
相关产品推荐
相关产品推荐

