Basically in the AppDelegate method of my app I connect to Firebase. I then need to initialize my UserProfileService before the app launches. Inside UserProfileService init I connect to Firebase to get the authenticated user data and store it.
The problem arises because if I don’t initialize UserProfileService before the app launches, as you can see in the code below, when I run the function .hasData() to check if the UserProfileService has inside it the data I need, it should either end up in the phoneRegistrationView or the mainTabBarView. If the user is indeed already authenticated, at app launch, since the initialization of UserProfileService needs to wait for Firebase to retrieve the data, the function .hasData() returns false and shows phoneRegistrationView() for a few milliseconds, then it returns to true and goes to mainTabBarView.
@main
struct myApp: App {
@StateObject private var userProfileService = UserProfileService()
var body: some Scene {
WindowGroup {
// user not registered or authenticated
if !userProfileService.hasData() {
NavigationView {
phoneRegistrationView()
}
.environmentObject(userProfileService)
}
// user registered and profile completed
else {
mainTabBarView()
.environmentObject(userProfileService)
}
}
}
Is there any way to solve this?
I tried await functions to initialize the data in UserProfileService but nothing seemed to work.
2
Answers
The
is an entry point to the app. Nothing should or will run before that. So you need to change your requirements and show some progress / loading screen while the data is being loaded:
While you could set
userProfileService.isLoading
totrue
in theinit
of theUserProfileService
, and set it back to false when you get a response from Firabase.This is of course the most primitive way, just to show the state. Many other ways are possible, but the point is: if you depend on some network operation, have a state in your app that "entertains" the user while that operation completes.
@StateObject
is for when you need a reference type in an@State
and both of these are for when you want a source of truth for view data tied to the lifetime of something on screen. I.e. created on appear and destroyed on disappear. Since you wouldn’t want your service to ever be destroyed@StateObject
is not the right tool for the job.Some other options are to use a singleton, see
PersistenceController.shared
in an Xcode template with core data checked. Or you could use the@UIApplicationDelegateAdaptor
that gives you a place you can create services and respond to the usual app lifecycle delegate events.