You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 08:33:25