ios - for 循环中的嵌套异步函数
问题描述
我对使用 Firebase Firestore 的 Swift 中的嵌套异步调用感到困惑。我正在尝试为我的应用程序创建一个朋友页面,该页面的一部分是用户朋友组的 UITableView。我将这些组存储在 Firebase 中的单独集合中,并尝试从组集合中的文档 ID 中获取当前用户所在的组列表。现在,看起来像这样:
func createGroupsArray(completion: @escaping ([Group]?) -> Void) {
let dispatchGroup1 = DispatchGroup()
let dispatchGroup2 = DispatchGroup()
var groups = [Group]()
let currentUser = User.current
guard currentUser.groupDocStrings.count > 0 else {
return completion(nil)
}
for g in currentUser.groupDocStrings {
dispatchGroup1.enter()
FirestoreService.db.collection(Constants.Firestore.Collections.groups).document(g).getDocument { (snapshot, err) in
if let err = err {
print("Error retrieving group document: \(err)")
return completion(nil)
} else {
let data = snapshot?.data()
var friends = [User]()
for f in data![Constants.Firestore.Keys.users] as! [String] {
dispatchGroup2.enter()
FirestoreService.db.collection(Constants.Firestore.Collections.users).document(f).getDocument { (snapshot, err) in
if let err = err {
print("Error retrieving user document: \(err)")
return completion(nil)
} else {
let uData = snapshot?.data()
friends.append(User(uid: f, data: uData!))
}
dispatchGroup2.leave()
}
}
dispatchGroup2.notify(queue: .main) {
let group = Group(groupName: data![Constants.Firestore.Keys.groupName] as! String, friends: friends)
groups.append(group)
}
dispatchGroup1.leave()
}
}
}
dispatchGroup1.notify(queue: .main) {
completion(groups)
}
}
但是当然,当我在我的 tableView(cellForRowAt) 函数中调用这个函数时,我不能返回一个单元格,因为它是异步的。我觉得必须有更好的方法来做到这一点,有什么帮助吗?
解决方案
无论您是否有数据,都要跟踪每一行。让 cellForRowAt() 返回一个单元格,如果有数据则返回一个单元格,如果没有数据则返回一个单元格。当您为一行下载数据时,存储数据,记住您拥有数据,并使该行无效。cellForRowAt() 将再次被调用,这次你用正确的数据填充它。
不要记住单元格对象,因为当您的异步调用返回时,它可能不再包含同一行的数据。如果您可以添加或删除行或更改排序顺序,则不要记住行号,因为当您的异步调用返回时,它可能不再是相同的行号了。
推荐阅读
- javascript - 为什么 export 返回 undefined 但是 module.exports 返回正确的数据
- python - 使用 shutil 忽略多个相同的子目录
- java - 使用 Retrofit with Field 传递参数
- python - Flask-RESTful fields.List 总是返回 None
- python - 如何将未排序的 numpy 数组中的数据映射到已排序的数组以进行插值?
- python - Ubuntu 终端自动执行 python 脚本。如何阻止它?
- css - 通过 Vue 样式加载器使用 CSS 模块的 NuxtJS 导致无法解释的错误
- android - AnyCharts Android 隐藏/重新加载信息
- javascript - 为什么在Vue中从数组中删除元素时会在最后一个索引处发生转换?
- html - Django ERR_EMPTY_RESPONSE