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

调整FirebaseApp.configure()位置触发SIGABRT,需优先注册远程通知

问题分析与解决方案

为什么原来在init()里调用FirebaseApp.configure()?

原来的代码在类的override init()中调用FirebaseApp.configure(),大概率是因为项目中存在依赖Firebase的组件(比如FIRAuth)在application:didFinishLaunchingWithOptions:之前就已经初始化了。举个例子,如果某个单例类的属性直接声明了let auth = Auth.auth(),这个属性会在该单例被创建时(可能早于didFinishLaunching)初始化,而Auth.auth()要求默认的FIRApp已经配置完成,所以必须提前在init()中完成Firebase配置,避免崩溃。

移到didFinishLaunching开头后崩溃的原因

你遇到的错误信息已经说得很明确:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'The default FIRApp instance must be configured before the default FIRAuthinstance can be initialized. One way to ensure that is to call [FIRApp configure]; is called in application:didFinishLaunchingWithOptions:.'

这说明你的项目里有代码在FirebaseApp.configure()之前就尝试初始化了FIRAuth实例。当你把FirebaseApp.configure()移到didFinishLaunching开头时,这个配置操作的时机还是晚于某个FIRAuth的初始化操作(比如某个单例的属性、全局变量等),所以触发了崩溃。

满足「先注册远程通知,再配置Firebase」的解决方案

要同时满足两个要求——registerForRemoteNotifications()在FirebaseApp.configure()之前执行,且FirebaseApp.configure()在所有依赖它的组件(比如FIRAuth)之前执行,你可以按照以下步骤调整代码:

1. 先处理远程通知注册(在Firebase配置之前)

修改application:didFinishLaunchingWithOptions:方法,先完成远程通知的注册逻辑,再调用Firebase配置:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // 第一步:先处理远程通知注册
    if #available(iOS 10, *) {
        UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
        Messaging.messaging().delegate = self
        // 先请求通知权限,完成后注册远程通知
        UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .sound, .alert]) { [weak self] granted, error in
            guard let self = self else { return }
            DispatchQueue.main.async {
                application.registerForRemoteNotifications()
            }
        }
        // 即使权限还没请求完成,也可以先注册(iOS会在授权通过后返回token)
        application.registerForRemoteNotifications()
    } else {
        let notificationSettings = UIUserNotificationSettings(types: [.badge, .alert, .sound], categories: nil)
        UIApplication.shared.registerUserNotificationSettings(notificationSettings)
        UIApplication.shared.registerForRemoteNotifications()
    }

    // 第二步:配置Firebase(现在在远程通知注册之后)
    FirebaseApp.configure()

    // 第三步:处理其他初始化逻辑(依赖Firebase的代码必须在这之后)
    GMSPlacesClient.provideAPIKey("AIzaSyCWMU53OSR4zO28i9e2BsASnda3X1TAS2Y")
    GMSServices.provideAPIKey("AIzaSyCWMU53OSR4zO28i9e2BsASnda3X1TAS2Y")
    UIApplication.shared.setStatusBarStyle(UIStatusBarStyle.lightContent, animated: true)
    UITabBarItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor:UIColor.clear], for: .normal)
    UITabBarItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor:UIColor.clear], for: .selected)
    
    // 注意:Messaging.messaging().fcmToken要在Firebase配置之后获取,否则会是nil
    DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
        print("Token is ", Messaging.messaging().fcmToken)
    }

    return true
}

2. 修复FIRAuth初始化过早的问题

检查项目中所有使用Auth.auth()的地方:

  • 如果是类属性/全局变量直接声明let auth = Auth.auth(),改成懒加载:
    lazy var auth: Auth = {
        return Auth.auth()
    }()
    
  • 如果是单例类在初始化时就创建了FIRAuth实例,把这部分逻辑延迟到FirebaseApp.configure()之后执行,比如在didFinishLaunching中调用单例的初始化方法,而不是让单例自动提前初始化。

3. 移除原来init()中的Firebase配置

把override init()里的FirebaseApp.configure()删掉,避免重复配置:

override init() {
    super.init()
    // 移除 FirebaseApp.configure()
}

额外注意点

  • Messaging.messaging().fcmToken必须在FirebaseApp.configure()之后才能获取到有效值,所以要调整打印时机,不要在Firebase配置之前打印。
  • iOS10+的通知授权是异步操作,所以registerForRemoteNotifications()可以在授权请求发起后立即调用,iOS会在用户授权通过后自动返回设备token。

内容的提问来源于stack exchange,提问作者bolt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:06:45