I have an AuthService with the following functions:
func signInAnon() -> AnyPublisher<User, AuthError> {
return Future<User, AuthError> { promise in
Auth.auth().signInAnonymously { result, error in
if let error = error {
return promise(.failure(.signInAnon(description: error.localizedDescription)))
} else if let user = result?.user {
return promise(.success(user))
}
}
}.eraseToAnyPublisher()
}
func linkAccount(email: String, password: String) -> AnyPublisher<User, AuthError> {
let emailCredential = EmailAuthProvider.credential(withEmail: email, password: password)
return Future<User, AuthError> { promise in
Auth.auth().currentUser?.link(with: emailCredential) { result, error in
if let error = error {
return promise(.failure(.linkAccount(description: error.localizedDescription)))
} else if let user = result?.user {
Auth.auth().updateCurrentUser(user) { error in
if let error = error {
return promise(.failure(.updateCurrentUser(description: error.localizedDescription)))
} else {
return promise(.success((user)))
}
}
}
}
} .eraseToAnyPublisher()
}
In my ViewModel, I want to link the user's anonymous account with an email/password credential. However, at the point of sign in, anonymous sign in has not happened.
Here is the code in my ViewModel:
case .signUp:
isLoading = true
authService.signInAnon()
.timeout(.seconds(5), scheduler: DispatchQueue.main, options: nil, customError: { () -> AuthError in
return .signInAnon(description: self.error?.localizedDescription)})
.sink { completion in
switch completion {
case let .failure(error):
self.error = error
case .finished:
print("User signed in anonymously")
self.error = nil
}
} receiveValue: { user in
self.user = user
}
.store(in: &cancellables)
authService.linkAccount(email: email, password: password)
.timeout(.seconds(5), scheduler: DispatchQueue.main, options: nil, customError: { () -> AuthError in
return .linkAccount(description: self.error?.localizedDescription)})
.sink { completion in
self.isLoading = false
switch completion {
case let .failure(error):
self.error = error
self.alertIsPresented = true
print(error.localizedDescription)
case .finished:
print("Sign up successful")
}
} receiveValue: { user in
self.user = user
}
.store(in: &cancellables)
I am running into problems because sometimes the function linking the accounts finishes before the anonymous sign in function, presenting an error.
How can I write this conditionally so that there is a check to see if the user is signed in anonymously? If they are, link their account. If they are not, sign them in anonymously, and then link their account.
Here's my recommendation for how to use Firebase Anonymous Auth:
Sample code for performing anonymous sign-in at app start-up (taken from this sample app ):
func signIn() {
if Auth.auth().currentUser == nil {
Auth.auth().signInAnonymously()
}
}
Sample code for upgrading to a Sign in with Apple account (taken from the same sample app ):
case .link:
if let currentUser = Auth.auth().currentUser {
currentUser.link(with: credential) { (result, error) in
if let error = error, (error as NSError).code == AuthErrorCode.credentialAlreadyInUse.rawValue {
print("The user you're signing in with has already been linked, signing in to the new user and migrating the anonymous users [\(currentUser.uid)] tasks.")
if let updatedCredential = (error as NSError).userInfo[AuthErrorUserInfoUpdatedCredentialKey] as? OAuthCredential {
print("Signing in using the updated credentials")
Auth.auth().signIn(with: updatedCredential) { (result, error) in
if let user = result?.user {
currentUser.getIDToken { (token, error) in
if let idToken = token {
(self.taskRepository as? FirestoreTaskRepository)?.migrateTasks(from: idToken)
self.doSignIn(appleIDCredential: appleIDCredential, user: user)
}
}
}
}
}
}
else if let error = error {
print("Error trying to link user: \(error.localizedDescription)")
}
else {
if let user = result?.user {
self.doSignIn(appleIDCredential: appleIDCredential, user: user)
}
}
}
}
If you're interested in how this would like for Combine, we've started implementing Combine support for Firebase - check out our project tracker
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.