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

如何解决Flutter iOS端点击Firebase推送通知后启动页闪退问题?

解决Flutter iOS点击FCM推送后崩溃的问题

根据你描述的情况——Flutter iOS能正常接收FCM推送,但点击后启动页显示随即崩溃,Android端完全正常,已经设置了异步main并调整过FCM代码位置,还没抓到异常日志——我给你几个针对性的排查和修复步骤,应该能解决问题:

1. 确保原生AppDelegate的推送回调在主线程执行

iOS的UI操作必须在主线程完成,哪怕Flutter侧做了处理,原生层的推送回调如果跑在非主线程,很容易触发崩溃。打开ios/Runner/AppDelegate.swift(如果是Objective-C项目就找对应的.m文件),检查并修改推送点击的处理方法:

Swift版本:

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    // 强制把所有操作放到主线程
    DispatchQueue.main.async {
        // 如果需要和Flutter通信,在这里调用MethodChannel
        if let flutterVC = window?.rootViewController as? FlutterViewController {
            let channel = FlutterMethodChannel(name: "fcm_notification_channel", binaryMessenger: flutterVC.binaryMessenger)
            channel.invokeMethod("onNotificationTap", arguments: response.notification.request.content.userInfo)
        }
        // 一定要调用completionHandler,否则系统会认为处理超时
        completionHandler()
    }
}

Objective-C版本:

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
    dispatch_async(dispatch_get_main_queue(), ^{
        FlutterViewController *flutterVC = (FlutterViewController *)self.window.rootViewController;
        FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"fcm_notification_channel" binaryMessenger:flutterVC];
        [channel invokeMethod:@"onNotificationTap" arguments:response.notification.request.content.userInfo];
        completionHandler();
    });
}

如果之前你没显式实现这个方法,FCM的默认处理可能在非主线程触发UI操作,这是iOS端推送崩溃的常见原因。

2. 调整异步main的初始化顺序

虽然你已经用了异步main,但如果FCM初始化和Flutter引擎启动的顺序不对,点击推送时可能引擎还没完全准备好。试试调整main函数的结构:

void main() async {
  // 先确保Flutter绑定初始化完成,这是异步操作的前提
  WidgetsFlutterBinding.ensureInitialized();
  
  // 初始化Firebase
  await Firebase.initializeApp();
  
  // 注册推送点击回调,放在引擎初始化之后
  FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
    // 这里处理跳转逻辑,比如导航到指定页面
    // 注意:如果是冷启动,要确保页面路由已经初始化完成
    print("Notification tapped: ${message.data}");
  });
  
  // 最后启动App
  runApp(const MyApp());
}

如果还是有问题,可以把推送回调的注册延迟到UI树构建完成后:

runApp(const MyApp());
WidgetsBinding.instance.addPostFrameCallback((_) {
  FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
    // 处理跳转逻辑
  });
});

3. 排查iOS配置的潜在问题

打开ios/Runner/Info.plist,检查两个关键配置:

  • 确认UIBackgroundModes包含remote-notification,保证App能在后台接收推送:
<key>UIBackgroundModes</key>
<array>
    <string>remote-notification</string>
</array>
  • 如果推送里包含HTTP链接,检查NSAppTransportSecurity设置,确保没有ATS限制导致崩溃:
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

(如果不想全局开启,可以添加指定域名的例外,更安全)

4. 强制捕获崩溃日志

你说没检测到异常,大概率是日志没抓到。试试这两种方法:

  • Xcode控制台捕获:用Xcode直接运行App到iPhone 7 Plus,然后点击推送触发崩溃,Xcode的控制台会输出完整的崩溃堆栈,能直接看到崩溃的原因。
  • Flutter全局异常捕获:在main函数里添加全局异常监听,捕获Flutter侧的未处理异常:
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // Flutter框架异常捕获
  FlutterError.onError = (FlutterErrorDetails details) {
    FlutterError.presentError(details);
    print("Flutter error: ${details.exception}");
    print("Stack trace: ${details.stack}");
  };
  
  // 异步任务异常捕获
  runZonedGuarded(() async {
    await Firebase.initializeApp();
    runApp(const MyApp());
  }, (error, stackTrace) {
    print("Uncaught async error: $error");
    print("Stack trace: $stackTrace");
  });
}

另外,在Xcode的Scheme设置里添加--verbose参数(Product > Scheme > Edit Scheme > Run > Arguments),运行时会输出更详细的Flutter日志,帮你定位问题。

5. 测试极简推送,排除数据解析问题

有时候推送的自定义数据格式不正确,Flutter侧解析时会崩溃。先发送一个不带任何自定义data的纯文本推送,点击看看是否还崩溃。如果不崩溃,再逐步添加自定义数据,排查是哪个字段导致的解析错误。


内容的提问来源于stack exchange,提问作者S. M. Asif

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 20:22:37