firebase-ios-sdk: Firebase Auth fails in SwiftUI App init
Description
PhoneAuthProvider.provider().verifyPhoneNumber.... will fail to execute. No success callback, no error either.
Reproducing the issue
On Xcode 14, While using the SwiftUI lifecyle, if you configure firebase in the @Main init() then Firebase auth wont work.
@Main
struct AppName: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
init() {
FirebaseApp.configure()
// This init method runs before `didFinishLaunchingWithOptions` in Xcode 14
}
}
The reason I even configured Firebase in the init method is because configuring it in the AppDelegate's didFinishLaunchingWithOptions method would crash my app since the @Main init() method runs first and I had firebase methods running in there before didFinishLaunchingWithOptions even executed meaning I was running firebase database functions before FirebaseApp.configure() ran.
So Running FirebaseApp.configure() in the @Main init() method would result in PhoneAuthProvider.provider().verifyPhoneNumber not working at all. no callback, no error nothing. But Running it in didFinishLaunchingWithOptions would work providing I ran my firebase database methods after a publisher told me it was safe to do so.
My temporary fix.
@MainActor
class AppDelegateObserver: ObservableObject {
@Published var didFinishLaunching = false
static var shared: AppDelegateObserver { AppDelegateObserver() }
}
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, OSSubscriptionObserver {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
AppDelegateObserver.shared.didFinishLaunching = true
return true
}
@Main
init() {
...
AppDelegateObserver
.shared
.$didFinishLaunching
.receive(on: RunLoop.main)
.sink { [weak self] didFinishLaunching in
/// Execute firebase database methods
}
.store(in: &disposables)
Ideally, I’d rather Configure Firebase in the @Main init() method than resort to this bandaid fix.
Hope that helps anyone who runs into this same issue. I tested with previous versions of Firebase eg. 9.4.1, 9.3.0 and the issue remained.
Firebase SDK Version
9.5.0
Xcode Version
14
Installation Method
Swift Package Manager
Firebase Product(s)
Analytics, Authentication, Crashlytics, DynamicLinks, Firestore, Functions
Targeted Platforms
iOS
Relevant Log Output
No response
If using Swift Package Manager, the project’s Package.resolved
Expand Package.resolved snippet
Replace this line with the contents of your Package.resolved.
If using CocoaPods, the project’s Podfile.lock
Expand Podfile.lock snippet
Replace this line with the contents of your Podfile.lock!
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 27 (7 by maintainers)
@forrestsyrett @onisiforos7 As I documented above, my solution was to have a trigger in
didFinishLaunchingWithOptionsthat will tell me when the app has launched, then I can run my firebase methods in my main ViewModel’s init method. It’s not ideal but it works atleast.@otymartin Would you provide some context on why Authentication needs to be initialized before
didFinishLaunching?@otymartin Just spent a whole day fixing the same issue. Dead silence, no errors or warnings. It did indeed have to do with the placement of
FirebaseApp.configure().The architecture of the iOS sdk is problematic. Global instances everywhere make the whole setup precarious.
@rizafran I did call it in
didFinishLaunchingafterward however my problem is that since@Main init()runs beforedidFinishLaunching, it means any firebase operations I run in my@Main init()will crash since firebase has not been configured yet.Authentication is one of those things I run as soon as the app launches.