首页 > 解决方案 > 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) 函数中调用这个函数时,我不能返回一个单元格,因为它是异步的。我觉得必须有更好的方法来做到这一点,有什么帮助吗?

标签: iosswiftfirebaseasynchronousgoogle-cloud-firestore

解决方案


无论您是否有数据,都要跟踪每一行。让 cellForRowAt() 返回一个单元格,如果有数据则返回一个单元格,如果没有数据则返回一个单元格。当您为一行下载数据时,存储数据,记住您拥有数据,并使该行无效。cellForRowAt() 将再次被调用,这次你用正确的数据填充它。

不要记住单元格对象,因为当您的异步调用返回时,它可能不再包含同一行的数据。如果您可以添加或删除行或更改排序顺序,则不要记住行号,因为当您的异步调用返回时,它可能不再是相同的行号了。


推荐阅读