FirebaseApp.configure() crashes app on launch
To answer my own question. I have solved this issue basically by removing Firebase/Core pod
from every project/target in Podfile
and add everything Firebase related to the main app target including Firebase/Analytics pod
(that means removing it from every other project/target).
After running pod install
I moved all files that used FirebaseAnalytics from custom framework to the main project (target). Now everything works as expected and calling [FIRApp configure];
does not crash the application.
Podfile
now looks something like this:
target 'TheApp' do
platform :ios, '11.0'
project 'TheApp/TheApp.xcodeproj'
use_frameworks!
pod 'Firebase/Analytics'
pod 'Firebase/Auth'
pod 'Firebase/Messaging'
pod 'Firebase/RemoteConfig'
end
target 'TheCustomFramework' do
platform :ios, '11.0'
project 'TheCustomFramework/TheCustomFramework.xcodeproj'
use_frameworks!
end
The default app has not been configured yet
Here's the answer to your problem:
To configure Firebase you have to execute FIRApp.configure() somewhere. After this is done you can use let firebaseDatabaseReference = FIRDatabase.database().reference() to get a reference to that database and start using it. The problem isn't with Firebase "per se" but with how Swift behaves.
If you put FIRApp.configure()
in your AppDelegate func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
and then in the MyDatabase class
you use let firebaseDatabaseReference = FIRDatabase.database().reference()
outside of your declared functions sometimes the code FIRDatabase.database().reference()
executes before the application didFinishLaunchingWithOptions
function is executed.
Essentially your class is trying to get a reference to the Firebase database before it has a chance to configure itself, generating the error in the console "The default app has not been configured yet."
Note: This doesn't happen all the time, sometimes the application is slow to start, in iOS Simulator for example, and it doesn't have a chance to finish before MyDatabase "let" executes and tries to get a reference.
That is why moving the FIRApp.configure() code to override init() in AppDelegate works, essentially it makes sure the configure code gets executed when AppDelegate is initialised (in this and most cases, before MyDatabase is initialised)
override init() {
super.init()
FIRApp.configure()
// not really needed unless you really need it FIRDatabase.database().persistenceEnabled = true
}
Also make sure you super.init() (so you super classes get the "message") so you override doesn't do more harm than good.
Firebase Auth user is outdated when using shared user access group
The documentation states:
Note: Shared keychain does not automatically update users across apps in real time. If you make a change to a user in one app, the user must be reloaded in any other shared keychain apps before the changes will be visible.
Here's some code to get you started:
func refreshUser() {
do {
let currentUser = Auth.auth().currentUser
let sharedUser = try Auth.auth().getStoredUser(forAccessGroup: accessGroup)
print("Current user: \(String(describing: currentUser)), shared User: \(sharedUser.uid)")
if currentUser != sharedUser {
updateUser(user: sharedUser)
}
}
catch {
do {
try Auth.auth().signOut()
}
catch {
print("Error when trying to sign out: \(error.localizedDescription)")
}
}
}
func updateUser(user: User) {
Auth.auth().updateCurrentUser(user) { error in
if let error = error {
print("Error when trying to update the user: \(error.localizedDescription)")
}
}
}
The following code shows how to use this in your main SwiftUI app, but can be easily adapted to a Widget:
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(authenticationService)
}
.onChange(of: scenePhase) { phase in
print("Current phase \(phase)")
if let user = Auth.auth().currentUser {
print("User: \(user.uid)")
}
else {
print("No user present")
}
if phase == .active {
// Uncomment this to refresh the user once the app becomes active
authenticationService.refreshUser()
}
}
}
Related Topics
How to Prevent Initial White Flash When Showing a Uiwebview
Where Is the Run Script and Build Phase in Xcode
Best Way to Save and Retrieve Uicolors to Core Data
How to Have a Fixed Uitableview Header While Using Sections
Swift How to Change Uialertcontroller's Title Color
Combining Text and Images in 'Uitextview'
Property "Assign" and "Retain" for Delegate
iOS Searchdisplaycontroller Prevents Tableview from Background Color Change (Background Stays Gray)
How to Reset the Application Data After Each Test with Xcode 7 UI Testing
Titletextattributes Uiappearance Font in iOS 7
Set Delegates to Nil Under Arc
How to Disable User Interaction on Mkmapview