返回Firebase用户名时出现iOS异步任务问题
我很快就要完成我项目的这一部分了。我学到了很多,但就是看不见,总结一下。我想做的是检查一个电子邮件地址是否已经被其他用户使用。为此,我使用以下代码:返回Firebase用户名时出现iOS异步任务问题,ios,swift,asynchronous,firebase-authentication,Ios,Swift,Asynchronous,Firebase Authentication,我很快就要完成我项目的这一部分了。我学到了很多,但就是看不见,总结一下。我想做的是检查一个电子邮件地址是否已经被其他用户使用。为此,我使用以下代码: func emailCheck(input : String, result:(canRegister: Bool?) -> Void){ var canRegister : Bool? FIRAuth.auth()?.signInWithEmail(input, password: " "){(user, error) in
func emailCheck(input : String, result:(canRegister: Bool?) -> Void){
var canRegister : Bool?
FIRAuth.auth()?.signInWithEmail(input, password: " "){(user, error) in
if error != nil {
if(error?.code == 17009){
print("Wrong Password")
canRegister = false
}else if(error?.code == 17011){
print("Unknown User")
canRegister = true
}else{
canRegister = false
}
}
}
}
整个Async
对我来说只有6个小时,所以如果你有任何建议,请告诉我。但按下按钮后,只需执行以下操作即可调用此函数:
print(emailCheck(emailTxt.text!){(canRegister : Bool?) -> Void in})
出于某种原因,这将返回空,而不是true
,false
甚至nil
。它只返回()
,但是当我输入正确的密码时,它确实返回了错误的密码
,不太确定这是否相关。有人能帮忙吗?谢谢大家
添加信息
建议之后,代码和对代码的引用现在看起来如下:(仅包括重要部分)
虽然这背后的过程是,如果返回的代码是用户不存在,那么电子邮件帐户将被拒绝,从而允许可以注册,否则,如果传入该帐户的空密码不正确,那么我们知道该帐户存在,因此无法使用注册。当前,canRegister
返回的值等于此处定义的值:
var canRegister = false
返回函数调用 您正在打印emailCheck
的返回值,这不是您想要的。异步只是意味着部分代码将在以后某个时间运行。考虑这个简单函数:
func emailCheck(input: String) -> Bool {
var valid = true
if input.characters.count == 0 {
valid = false
}
return valid
}
这只是检查电子邮件是否有超过零个字符。它可以大大简化,但为了说明不同之处,我把它简化了一点。要使用它,您只需执行以下操作:
let isValid = emailCheck("me@example.com")
if isValid {
print("Valid!")
} else {
print("Invalid!")
}
emailCheck("me@example.com") { isValid in
if isValid {
print("Valid!")
} else {
print("Invalid!")
}
}
如果我们希望该方法能够异步工作,我们将为其提供回调。回调只是一个函数,可以调用它让我们知道结果是什么,而不是由函数直接返回结果。下面是它的样子:
func emailCheck(input: String, callback: (isValid: Bool) -> Void) {
var valid = true
if input.characters.count == 0 {
valid = false
}
callback(isValid: valid)
}
func callback(isValid: Bool) {
if isValid {
print("Valid!")
} else {
print("Invalid!")
}
}
emailCheck("me@example.com", callback: callback)
请注意,emailCheck
不再返回值,而是实际使用结果执行回调方法。这还不是真正的异步,因为回调是立即执行的,但它允许我们在需要时执行异步操作
Swift有一些简洁的语法,可以将回调作为最后一个参数传递,而不用像上面那样显式地声明它们。这是您用于Firebase的通过电子邮件登录的方法。在这段代码中使用它,看起来像这样:
let isValid = emailCheck("me@example.com")
if isValid {
print("Valid!")
} else {
print("Invalid!")
}
emailCheck("me@example.com") { isValid in
if isValid {
print("Valid!")
} else {
print("Invalid!")
}
}
它的功能完全相同,但我认为它在这种情况下看起来更好一点。所以现在我们有了一个很好的设置,可以检查电子邮件,还有一些代码可以在我们知道电子邮件是否有效后运行。总而言之:
func emailCheck(input: String, callback: (isValid: Bool) -> Void) {
FIRAuth.auth()?.signInWithEmail(input, password: " ") { (user, error) in
var canRegister = false
if error != nil {
if (error?.code == 17009) {
print("Wrong Password")
} else if(error?.code == 17011) {
print("Unknown User")
canRegister = true
}
}
callback(isValid: canRegister)
}
}
var availableEmail = false
emailCheck("me@example.com") { isValid in
if isValid {
print("Valid!")
} else {
print("Invalid!")
}
availableEmail = isValid
// This prints **second**, and should print `true`, if `isValid` was true.
print(availableEmail)
}
// This prints **first**, and should print `false`, because the callback likely has not run yet.
print(availableEmail)
编辑:请参阅上面的打印
代码/注释,这些注释说明了在使用回调方法时变量如何不会立即更新
附加编辑:另一种结构方式,为清晰起见,使用另一种功能:
emailCheck("me@example.com") { isValid in
if isValid {
print("Valid!")
} else {
print("Invalid!")
}
self.emailCheckComplete(isValid)
}
func emailCheckComplete(availableEmail: Bool) {
// This is the same as above, but perhaps helps you follow the flow.
print(availableEmail)
}
嗯,是的,isValid
是类型Bool
,因此您可以执行回调(isValid:true)
,但是如果电子邮件被接收呢?你会想用false。这就是为什么我使用了canRegister
,这也是一个Bool
,并相应地设置为true/或false。在我的示例中,emailCheck
没有返回任何值,可能我不理解你的意思。你能根据我的示例用你所做的更改编辑你的帖子吗?查看更新的代码有助于理解您的意思。不,availableEmail
正在更新…但您可能在回调方法的范围之外使用它。在这种情况下,您正在更新它之前使用它。理解代码的每一部分何时运行是一个关键问题,在您第一次学习时很容易出错。记住,回调只会在将来的某个时候运行。它之外的任何代码都会立即运行。由于格式限制,很难在注释中演示,有关更多详细信息,请参阅我的答案编辑。回调是一个完成:
块。我只是选择将它命名为callback:
,但您可以将它命名为completion:
。这只是语义学。但只有其中的代码才能访问更新的值。您可以从该块中调用函数,我发现这有助于澄清代码的流动方式。请参阅其他编辑。更新的代码在我看来是正确的。似乎出于某种原因,您没有从Firebase获得错误代码17011。深入研究他们的文档,我认为他们的API并没有按照您所期望的方式运行。根据,FIRAuthErrorCodeUserNotFound
错误(与您使用的17011代码相匹配)“表示未找到用户帐户。如果用户帐户已被删除,则可能发生这种情况。”我不清楚这是否是引发该错误的唯一情况……无论如何,更深入地了解你正在尝试做的事情的根源……在我看来,你可能正在尝试处理他们为你处理的事情。对于createUserWithEmail
方法来说,它会抛出一个FirautherRorCodeEmailalReadyUse
错误,这似乎就是您试图自己处理的问题。为什么不试着创建它并处理这个错误呢?@dbburges你知道它是什么吗?我在这行中缺少了一个空格:…使用电子邮件登录(输入,密码:)…
因为密码
没有空格firebase没有将其作为空密码读取,而更像是nil
,这样就不会引发错误。谢谢你的帮助!再次感谢你令人惊讶的回答,希望其他与此斗争的人也会投票!