Я пытаюсь написать специальную функцию, которая регистрирует нового пользователя в Firebase. Я импортировал Firebase в класс с именем DatabaseManager. Там я управляю всем взаимодействием с базой данных. В этом классе я хотел бы иметь настраиваемую функцию для добавления пользователей, которая выдает все ошибки Firebase. Это значит, что я могу использовать функцию в классе ViewController, где я могу обнаруживать ошибки и показывать предупреждения. Однако я не могу заставить эту функцию работать должным образом, и я не уверен, что делаю неправильно.
Вот моя функция:
enum createAccountError : Error{
case emailInUse, weakPassword, networkError, unknownError
}
//Mark: create a user profile
///create account with email, password, username, phoneNumber, birthDate, name
func createAccount(_ userModel: UserModel, _ password: String?, completion: @escaping (_ inner: ()throws -> Bool)->()) {
Auth.auth().createUser(withEmail: userModel.email!, password: password!, completion: {(user, error) in
if let error = error {
if let errCode = AuthErrorCode(rawValue: error._code) {
switch errCode {
case .emailAlreadyInUse:
completion({throw createAccountError.emailInUse})
case .weakPassword:
completion({throw createAccountError.weakPassword})
case .networkError:
completion({throw createAccountError.networkError})
default:
completion({throw createAccountError.unknownError})
}
}
return
} else {
completion({return true})
}
})
}
И вот как я пробовал его использовать:
DatabaseManager.system.createAccount(user, password) { (( inner: ()throws -> Bool)->()) in
do{
let result = try inner()
} catch .emailInUse{
//show alert
}
}
2 ответа
Я создал тестовую функцию для демонстрации, и все работает правильно
// error type
enum TestError: Error { case notFound, empty }
// define typealias for eiser usage of complex function type
typealias ThrowableCallback = () throws -> Bool
func createAccount(_ shouldThrow: Bool, completion: @escaping (_ inner: ThrowableCallback) -> Void) {
// call completion callback asynchronously
DispatchQueue.main.async {
if shouldThrow {
// throw error
completion({ throw TestError.notFound })
}
// return value
completion({ return true })
}
}
Применение:
createAccount(true) { (inner: ThrowableCallback) -> Void in
do {
let success = try inner()
print(success)
} catch {
print(error)
}
}
UPD: я не рекомендую использовать эту технику для обработки ошибок в асинхронных функциях. Используйте отдельные обратные вызовы для успеха и неудачи или обещания для корректной обработки асинхронного кода (подробнее см. this)
UPD 2: Актуальное решение
typealias ThrowableCallback = () throws -> User
func createAccount(_ userModel: UserModel,
_ password: String,
completion: @escaping (_ inner: ThrowableCallback) -> Void) {
Auth.auth().createUser(withEmail: userModel.email!, password: password!, completion: {(user, error) in
if let error = error { completion({ throw error }) }
else { completions({ return user! }) }
})
}
// usage
createAccount(userModel, somePassword) { (inner: ThrowableCallback) -> Void in
do {
let createdUser = try inner()
} catch {
ler errCode = (error as NSError)._code
switch errCode {
case .emailAlreadyInUse:
showAlert("Email is already in use")
case .weakPassword:
showAlert("please enter stronger password ")
case .networkError:
showAlert("it seams that there is no internet connection")
default:
showAlert("Error creating user. Please try again later")
}
}
}
Я бы предложил провести рефакторинг вашей функции следующим образом:
func createAccount(_ userModel: UserModel, _ password: String?, completion: @escaping(Error?) -> ()) {
Auth.auth().createUser(withEmail: userModel.email!, password: password!, completion: {(user, error) in
if let error = error {
if let errCode = AuthErrorCode(rawValue: error._code) {
switch errCode {
case .emailAlreadyInUse:
completion(createAccountError.emailInUse)
case .weakPassword:
completion(createAccountError.weakPassword)
case .networkError:
completion(createAccountError.networkError)
default:
completion(createAccountError.unknownError)
}
}
} else {
completion(nil)
}
})
}
Затем, когда вы вызываете функцию, вы можете проверить, не было ли такой ошибки:
DatabaseManager.system.createAccount(user, password) { (error) in
guard error == nil else {
//Handle error
return
}
//There was no error
Похожие вопросы
Новые вопросы
swift
Swift - это безопасный, быстрый и выразительный язык программирования общего назначения, разработанный Apple Inc. для своих платформ и Linux. Swift с открытым исходным кодом. Используйте тег только для вопросов о языковых функциях или необходимости кода в Swift. Используйте теги [ios], [ipados], [macos], [watch-os], [tvos], [cocoa-touch] и [cocoa] для (не зависящих от языка) вопросов о платформах или фреймворках.