集成Firebase Cloud Messaging后AppDelegate多数方法未触发问题
解决集成FCM后AppDelegate生命周期方法不触发的问题
嘿,我之前也碰到过一模一样的情况!其实这和FCM本身没太大关系,主要是iOS 13+引入的SceneDelegate在搞事情——当你的App启用了Scene配置后,原来属于AppDelegate的大部分生命周期事件会被转移到SceneDelegate中执行,导致你看到的applicationWillResignActive这类方法不再被调用。
下面给你几个针对性的解决方案,你可以根据自己的项目需求选择:
方案1:回到旧的单App生命周期模式(放弃SceneDelegate)
如果你的App不需要支持iPad多窗口这类Scene特性,最简单的方法是直接禁用Scene配置:
- 打开项目的
Info.plist,找到并删除UIApplicationSceneManifest这个字典条目(整个删掉,包括它下面的所有子项)。 - 删掉项目中的
SceneDelegate.swift文件(如果有的话)。 - 确保你的
AppDelegate中保留var window: UIWindow?的声明(你的代码里已经有了)。
做完这些操作后,AppDelegate的所有生命周期方法就会恢复正常触发了。
方案2:保留SceneDelegate,迁移逻辑到对应方法
如果你的App需要支持Scene特性(比如iPad多窗口),那就要把原来AppDelegate中的逻辑迁移到SceneDelegate的对应方法里,两者的对应关系如下:
| AppDelegate方法 | SceneDelegate对应方法 |
|---|---|
applicationWillResignActive | sceneWillResignActive |
applicationDidEnterBackground | sceneDidEnterBackground |
applicationWillEnterForeground | sceneWillEnterForeground |
applicationDidBecomeActive | sceneDidBecomeActive |
举个例子,你的SceneDelegate应该写成这样:
import UIKit import Firebase class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } // 初始化Window(如果AppDelegate里没做的话) self.window = UIWindow(windowScene: windowScene) self.window?.rootViewController = LoadingViewController.instantiate() self.window?.makeKeyAndVisible() // 确保通知代理指向AppDelegate(因为你的FCM相关代理逻辑在AppDelegate里) UNUserNotificationCenter.current().delegate = UIApplication.shared.delegate as? AppDelegate Messaging.messaging().delegate = UIApplication.shared.delegate as? AppDelegate } func sceneWillResignActive(_ scene: UIScene) { log.verbose("sceneWillResignActive") // 原applicationWillResignActive的逻辑移到这 } func sceneDidEnterBackground(_ scene: UIScene) { log.verbose("sceneDidEnterBackground") RideController.shared.prepareForBackground() } func sceneWillEnterForeground(_ scene: UIScene) { log.verbose("sceneWillEnterForeground") // 原applicationWillEnterForeground的逻辑移到这 } func sceneDidBecomeActive(_ scene: UIScene) { log.verbose("sceneDidBecomeActive") RideController.shared.prepareForForeground() WatchController.shared.startSession() } }
额外检查点
- 确认你的
AppDelegate中FirebaseApp.configure()只调用一次(你的代码里在didFinishLaunchingWithOptions里调用是对的)。 - 确保没有其他第三方库抢占了
UNUserNotificationCenter或Messaging的代理设置。
内容的提问来源于stack exchange,提问作者matmat
相关产品推荐
相关产品推荐

