Swift 函数接受转义闭包时抛出错误

Swift 函数接受转义闭包时抛出错误,swift,escaping,closures,try-catch,throw,Swift,Escaping,Closures,Try Catch,Throw,我正在尝试编写一个自定义函数,在Firebase中注册一个新用户。我已在名为DatabaseManager的类中导入Firebase。在那里,我管理所有数据库交互。在这个类中,我希望有一个用于添加用户的自定义函数,它抛出所有Firebase错误。这样我就可以在ViewController类中使用该函数,在该类中我可以捕获错误并显示警报。 然而,我似乎无法让功能正常工作,我不知道我做错了什么 以下是我的功能: enum createAccountError : Error{ cas

我正在尝试编写一个自定义函数,在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
            }
            }

我建议按如下方式重构您的函数:

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

我已经创建了用于演示的测试函数,并且一切正常

//错误类型
枚举测试错误:错误{case notFound,empty}
//为复杂函数类型的eiser用法定义typealias
typealias ThrowableCallback=()抛出->布尔
func createAccount(uu-shouldThrow:Bool,completion:@escaping(uu-inner:ThrowableCallback)->Void){
//异步调用完成回调
DispatchQueue.main.async{
如果该扔{
//抛出错误
完成({throw TestError.notFound})
}
//返回值
完成({return true})
}
}
用法:

createAccount(true){(内部:ThrowableCallback)->Void in
做{
让成功=尝试内在()
打印(成功)
}抓住{
打印(错误)
}
}
UPD:我不建议使用这种技术来处理异步函数中的错误。对成功和失败使用单独的回调,或承诺优雅地处理异步代码(查看了解更多信息)

UPD 2:实际解决方案

typealias ThrowableCallback=()抛出->用户
func createAccount(userModel:userModel,
_密码:String,
完成:@escaping(uu内部:ThrowableCallback)->Void){
Auth.Auth().createUser(电子邮件:userModel.email!,密码:password!,完成:{(用户,错误)在
如果let error=error{completion({throw error})}
else{completions({return user!})}
}) 
}
//用法
CreateCount(userModel,somePassword){(内部:ThrowableCallback)->中的Void
做{
让createdUser=try internal()
}抓住{
ler errCode=(错误为NSError)。\u代码
开关错误码{
案例。EmailalReadyUse:
showAlert(“电子邮件已在使用”)
case.weakPassword:
showAlert(“请输入更强的密码”)
案例.网络错误:
showAlert(“表示没有internet连接”)
违约:
showAlert(“创建用户时出错。请稍后重试”)
}
}
}

请更新您的问题(不要发表评论),以清楚地解释您发布的代码存在哪些问题。maddy,我不确定您的意思,我只是问如何使用函数。我使用它的方式不起作用。“不起作用”不是一个有用的说法。它到底在什么方面不起作用?我喜欢你的解决方案。关于不使用它的建议,请看我这样做的全部原因是因为我想在另一个类中处理Firebase错误,我将在该类中使用此函数createAccount()。老实说,重新阅读我的代码,我认为从开关案例中生成更多的枚举可能不是最好的方法,但我不确定如何将authorCode错误转出。这样我可以在其他类中处理它。你知道我怎么做吗?很好,看起来很棒。我试试看。谢谢Sandy C,所以我实际上在您的代码中遇到了一个问题。使用它时,行let errCode=(错误为NSError)。\u code,错误类型实际上是AuthErrorCode。所以问题是,我不能在我计划使用函数的类中继续使用它。怎么解决这个问题?@dre_84w934对不起,我忘了这个。您应该使用以下代码将其转换为AuthErrorCode类型
let errCode=AuthErrorCode(rawValue:(错误为NSError)。\u code)
。是的,你是对的,这是最简单的部分:)让我知道这个解决方案是否适合你,我会更新我的答案