ios - 当每次都没有进入for循环时,如何等到在Swift中执行查询?
问题描述
我想检查我的任何用户在创建新帐户期间是否使用与我的新用户相同的用户名。如您所见,我正在使用查询从 firebase 获取文档,但 usernameTaken() 比执行查询更快地返回输出。我正在尝试使用 DispatchGroup(第一次),但我无法获得我想要的结果。基本上,一旦进入 for 循环,我想更改变量 isTaken 的值。这是我的 usernameTaken() 函数,带有 Firebase 查询和 DispatchGroup 尝试:
func usernameTaken() -> Bool {
let currentUsername = usernameTextField.text
var isTaken = false
let group = DispatchGroup()
db.collection((K.FStore.usersCollection)).whereField(K.FStore.usernameField, isEqualTo: currentUsername!)
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
group.enter()
print("Same username ID: \(document.documentID)")
print("Username used")
isTaken = true
group.leave()
}
}
}
group.notify(queue: .main) {
print(isTaken)
print("Group notify")
}
print("82 : \(isTaken)")
return isTaken
}
据我所知,当不使用用户名时,不会输入 for 循环。我在这里做错了什么?也许有更好的方法来检查用户名是否已在 Firebase 中使用?感谢您的时间和帮助!
解决方案
您的函数(对 Firestore 进行网络调用)不能是同步的——这意味着它会在函数有效完成后立即返回(在本例中为布尔值)。那是因为 Firestore 需要一些时间来查询数据库并返回您的文档。因此,您的函数本质上应该是异步的,这意味着它可以在控制退出函数后“返回”事物。而在 Swift 中,最好的方法是通过完成处理程序。
func usernameTaken(_ completion: @escaping (_ taken: Bool?) -> Void) {
let currentUsername = usernameTextField.text
db.collection((K.FStore.usersCollection)).whereField(K.FStore.usernameField, isEqualTo: currentUsername!).getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
completion(nil) // error; unknown if taken
} else {
if querySnapshot!.isEmpty {
completion(false) // no documents; not taken
} else {
completion(true) // at least 1 document; taken
}
}
}
}
usernameTaken { (taken) in
guard let taken = taken else {
return // value is nil; there was an error—consider retrying
}
if taken {
print("username is taken")
} else {
print("username is available")
}
}
我还将返回值设为可选布尔值,以便调用者可以判断是否有错误(当值为 时nil
)。
推荐阅读
- r - 循环 ARIMA 组合以最小化 RMSE
- php - if else 语句用于标识数组中的最后一项
- javascript - 我放在按钮上的 EventListener 在第一次点击时不起作用
- c# - 使用运行 Oracle 单记录更新/插入的绑定变量是否有优势?
- java - 从 jsonobj 中提取数据的 Java Stream 表示
- r - 使用 stat_summary 在箱线图上标注中线
- google-cloud-platform - 如何让 Google Cloud Build 在 VPC 边界内工作?
- pythonanywhere - 如何使用 Python Flask 上传照片并将其保存到网站中
- python - 在更新中隐藏特定字段,但在创建中不隐藏
- xml - 在 Apache NiFi 的 ExecuteScript 处理器中缓存文件内容