我正在尝试编写一个在 Firebase 中注册新用户的自定义函数。我在一个名为 DatabaseManager 的类中导入了 Firebase。在那里,我管理所有数据库交互。在这个类中,我想要一个用于添加用户的自定义函数,它会抛出所有 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
}
}
最佳答案
我已经为演示创建了测试函数,一切正常
// 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:我不建议使用这种技术来处理异步函数中的错误。对成功和失败使用单独的回调或 Promises 以优雅地处理异步代码(查看 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")
}
}
}
关于swift - 在采用转义闭包的函数中抛出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48038318/