iOS集成Firebase报FIRAppNotConfigured崩溃及API拦截问题
崩溃和API被拦截的问题本质是Firebase SDK的初始化顺序强依赖冲突:
- 所有Firebase生态组件实例(包括
FIRRemoteConfig、FIRPerformance)必须在[FIRApp configure]执行完成后才能创建,否则会直接抛出FIRAppNotConfigured异常,这也是把configure调用放在Remote Config初始化逻辑之后触发崩溃的直接原因,对应崩溃日志核心信息:
*** Terminating app due to uncaught exception 'FIRAppNotConfigured', reason: 'The default
FirebaseAppinstance must be configured before the default Remote Config instance can be initialized. One way to ensure this is to callFirebaseApp.configure()in the App Delegate'sapplication(_:didFinishLaunchingWithOptions:)or the@mainstruct's initializer in SwiftUI.'
- Firebase Performance会在
[FIRApp configure]执行过程中自动启动监控、注册全局网络拦截逻辑,如果在configure执行完成后才修改instrumentationEnabled和dataCollectionEnabled开关,已经注册的拦截逻辑不会被撤销,就会出现提前拦截部分API响应的问题。 - 官方禁用SDK文档中提到的「configure前设置开关」,针对的是Info.plist静态配置或本地预设值场景,不支持在configure前调用Remote Config动态拉取配置值。
方案1:本地预设开关+远程配置延后更新(兼容性最好,零崩溃)
该方案完全规避初始化顺序冲突,核心逻辑是启动时先用本地持久化存储的开关值在configure前预设Performance状态,避免拦截器提前注册,等SDK初始化完成后再拉取远程配置更新开关,新值可选择当前运行期即时生效或下次冷启动生效。
对应实现代码:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ // 读取上次启动时持久化的性能监控开关值,必须在FIRApp configure前设置 BOOL perfDisabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"kRemotePerfDisablePersistKey"]; [FIRPerformance sharedInstance].instrumentationEnabled = !perfDisabled; [FIRPerformance sharedInstance].dataCollectionEnabled = !perfDisabled; // 执行Firebase核心初始化,此时不会触发崩溃,也不会注册多余的网络拦截逻辑 [FIRApp configure]; // 核心初始化完成后再创建Remote Config实例 self.remoteConfig = [FIRRemoteConfig remoteConfig]; FIRRemoteConfigSettings *remoteConfigSettings = [[FIRRemoteConfigSettings alloc] init]; remoteConfigSettings.minimumFetchInterval = 0; self.remoteConfig.configSettings = remoteConfigSettings; [self.remoteConfig setDefaultsFromPlistFileName:@"RemoteConfigDefaults"]; // 拉取并激活远程配置,更新本地持久化的开关值 [self.remoteConfig fetchAndActivateWithCompletionHandler:^(FIRRemoteConfigFetchAndActivateStatus status, NSError * _Nullable error) { if (status != FIRRemoteConfigFetchAndActivateStatusError) { BOOL remotePerfDisabled = [self.remoteConfig configValueForKey:@"perf_disable"].boolValue; // 持久化最新开关值,供下次冷启动时在configure前读取 [[NSUserDefaults standardUserDefaults] setBool:remotePerfDisabled forKey:@"kRemotePerfDisablePersistKey"]; [[NSUserDefaults standardUserDefaults] synchronize]; // 如需当前运行期即时生效,可在此处更新Performance开关 [FIRPerformance sharedInstance].instrumentationEnabled = !remotePerfDisabled; [FIRPerformance sharedInstance].dataCollectionEnabled = !remotePerfDisabled; } }]; return YES; }
注意:首次安装启动时本地没有持久化值,默认会读取NSUserDefaults的初始值NO(即性能监控开启),如果需要和远程配置默认值保持一致,可以在代码中首次启动时先读取Remote Config默认plist中的perf_disable值作为初始预设值即可。
方案2:关闭Performance自动初始化
直接在项目Info.plist中添加两个配置项,值均设为NO:
FirebasePerformanceAutomaticScreenReportingEnabledFirebasePerformanceCollectionEnabled
配置完成后,[FIRApp configure]执行时不会自动初始化Performance组件,也不会注册网络拦截器。等Remote Config初始化完成、拉取到perf_disable开关值后,再手动设置instrumentationEnabled和dataCollectionEnabled即可,不会出现API被提前拦截的问题。
- 绝对不要在
[FIRApp configure]执行完成前调用任何Firebase组件的实例获取方法,包括[FIRRemoteConfig remoteConfig],否则必然触发初始化异常。 - Performance的全局网络拦截逻辑是在组件初始化阶段注入的,只有在FIRApp加载Performance组件前就将开关设为禁用,才能完全阻止拦截逻辑注册;configure之后再修改开关,只能停止后续监控数据上报,无法移除已经注入的拦截器。
内容的提问来源于stack exchange,提问作者Siva

