Reputation: 2525
I have an app where users can sign up and login using Firebase. However, I can not seem to alert the user of any errors in the view.
First we have a UserStore which is a ObservableObject
and is initialised as an EnvironmentObject
when setting up the view in the SceneDelegate
.
let appView = AppView().environmentObject(userStore)
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: appView)
self.window = window
window.makeKeyAndVisible()
}
Then we sign up or login to the View like so.
In View
self.userStore.logIn(email: self.email, password: self.password)
self.isLoggingIn = true
if self.userStore.failedToLogin {
self.isLoggingIn = false
self.alertTitle = "There seems to be a problem"
self.alertBody = self.userStore.errorMessage
self.showingAlert = true
}
Then the actual method should update the UserStore property values which then update the view and display an alert, however, this is not the case.
SignIn
// Session Properties
@Published var isLoggedIn = false {didSet{didChange.send() }}
@Published var isNewUser = false {didSet{didChange.send() }}
@Published var failedToCreateAccount = false {didSet{didChange.send() }}
@Published var failedToLogin = false {didSet{didChange.send() }}
@Published var errorMessage = "" {didSet{didChange.send() }}
init () {
handle = Auth.auth().addStateDidChangeListener { (auth, user) in
if let user = user {
self.session = user
self.isLoggedIn = true
//Change isNewUser is user document exists?
} else {
self.session = nil
self.isLoggedIn = false
}
}
}
func logIn(email: String, password: String) {
Auth.auth().signIn(withEmail: email, password: password) { [weak self] user, error in
print("Signed In")
if(error != nil) {
print("Failed to login")
self!.failedToLogin = true
self!.errorMessage = ("\(String(describing: error))")
print(error!)
return
} else if error == nil {
print("Success Logging In")
}
}
}
The AppView determines which view is loaded depending if the user is logged in.
AppView
if !userStore.isLoggedIn {
LoginView().transition(.opacity)
}
if userStore.isLoggedIn {
ContentView().transition(.opacity)
}
Atm error messages are not shown; the login view is also shown shortly before the main view.
How can I correctly display error messages in the view ?
Upvotes: 1
Views: 1583
Reputation: 194
Use Combine Firebase: https://github.com/rever-ai/CombineFirebase
This is combine-swiftui wrapper around firebase api, so you can use swift-ui publisher pattern for firebase.
Upvotes: 0
Reputation: 7254
The Firebase APIs are asynchronous, simply because they access a remote system, across the internet, which takes a little time. The same applies for accessing the local disk, by the way. This blog post explains this in more detail.
Consequently, userStore.login
is an asynchronous process. I.e. the call to if self.userStore.failedToLogin
is executed before userStore.login
returns. Thus, userStore.failedToLogin
is still false
, and the code in the conditional statement will never be executed.
There are two ways around this:
userStore.logIn
, and move the code which displays the error into the closure userStore.failedToLogin
a publisher and subscribe the visibility of your alert to itUpvotes: 2