返回 Firebase 用户名时的 iOS 异步任务问题
Posted
技术标签:
【中文标题】返回 Firebase 用户名时的 iOS 异步任务问题【英文标题】:iOS Async Task Issue When Returning Firebase Usernames 【发布时间】:2016-07-30 22:50:15 【问题描述】:我非常接近完成我的项目的这一部分。我学到了很多,但就是看不到,总结一下。我要做的基本上是检查电子邮件地址是否已被其他用户使用。为此,我正在使用以下代码:
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
。它只返回()
但是当我输入正确的密码时它确实返回Wrong Password
,不太确定这是否相关。有人可以帮忙吗?谢谢大家!
添加信息 经过建议,代码和对代码的引用现在看起来像这样:(仅包含重要部分)
class LoginViewController: UIViewController
@IBAction func nextScreen(sender: UIButton)
emailCheck(emailTxt.text!) 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)
//wrong password error
else if(error?.code == 17011)
//email doesn't exist
canRegister = true
callback(isValid: canRegister)
这背后的过程是,如果返回的代码是用户不存在,那么邮箱账号是开放的,可以被抵抗,从而允许canRegister
,否则,如果传入的密码是空的不正确,那么我们知道该帐户存在,因此无法注册使用。目前,canRegister
返回的值等于此处定义的值:
var canRegister = false
返回函数调用。
【问题讨论】:
更新后的代码对我来说是正确的。由于某种原因,您似乎没有从 Firebase 收到错误代码 17011。深入研究他们的文档,我认为他们的 API 的行为与您预期的不同。根据this page,FIRAuthErrorCodeUserNotFound
错误(与您使用的 17011 代码匹配)“表示未找到用户帐户。如果用户帐户已被删除,可能会发生这种情况。”不是如果这是引发该错误的唯一情况,我很清楚......
无论如何,要更深入地了解您正在尝试做的事情......在我看来,您可能正在尝试处理他们为您处理的事情。 createUserWithEmail
方法的 docs 表示它可能会引发 FIRAuthErrorCodeEmailAlreadyInUse
错误,这似乎就是您要自己处理的问题。为什么不尝试创建它并处理这个错误呢?
@dbburgess 你知道它是什么吗?我在这一行中遗漏了一个空格:...signInWithEmail(input, password: " ") ...
因为password
没有空格,所以firebase 没有将其读取为空密码,而可能更像是nil
,这样就不会引发错误。感谢您的所有帮助!
再次感谢您的精彩回答,希望其他为此苦苦挣扎的人也会投票!
【参考方案1】:
您正在打印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!")
如果我们希望该方法能够异步工作,我们会为其提供回调。回调只是一个函数,可以调用它让我们知道结果是什么,而不是直接由函数返回。看起来是这样的:
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 的 signInWithEmail
方法的内容。在这段代码中使用它,它看起来像这样:
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)
编辑:参见上面的print
代码/cmets,它说明了当您使用回调方法时变量不会立即更新。
附加编辑:另一种结构方式,为了清楚起见使用另一个函数:
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
类型,所以你可以使用callback(isValid: true)
,但是如果电子邮件被占用了怎么办?你想用假的。这就是我使用canRegister
的原因,它也是Bool
并相应地设置为true / 或false。
在我的例子中,emailCheck
没有返回 any 值,但也许我不明白你的意思。
您可以根据我的示例使用您所做的更改来编辑您的帖子吗?查看更新后的代码有助于理解您的意思。
不,availableEmail
正在更新...但您可能在在回调方法的范围之外使用它。在这种情况下,您正在使用它之前它被更新。了解何时代码的每个部分运行是至关重要的,并且在您第一次学习时很容易出错。请记住,回调仅在将来的某个时间运行。它之外的任何代码都会立即运行。由于格式限制,很难在 cmets 中演示,请参阅我的答案编辑以了解更多详细信息。
回调是一个completion:
块。我只是选择将其命名为callback:
,但您可以将其命名为completion:
。这只是语义。但只有其中的代码才能访问更新的值。您可以从该块中调用一个函数,我发现它可以帮助澄清代码的流动方式。查看其他修改。以上是关于返回 Firebase 用户名时的 iOS 异步任务问题的主要内容,如果未能解决你的问题,请参考以下文章
只有在 SwiftUI 和 Firebase 中完成循环中的异步调用时,如何才能返回函数?
Firebase Auth iOS用户匿名创建但未在控制台中显示