【问题标题】:Not all elements of my array are being used at the same time (swift)并非我的数组的所有元素都在同时使用(swift)
【发布时间】:2021-03-17 19:51:01
【问题描述】:

我有一个我关注的用户的动态数组(名为“items”):

["user5@t.co", " user6@t.co"]

我实际上是在使用以下方法检索这些用户的帖子:

for i in 0..< items.count{
                
                db.collection("users").document("\(items[i])").collection("posts").addSnapshotListener { (querySnapshot, error) in
                    guard let documents = querySnapshot?.documents else {
                        print("No documents")
                        return
                    }

                    self.posts = documents.map { QueryDocumentSnapshot -> Post in
                        let longitudeVar = data["longitude"] as? String ?? ""
                        let latitudeVar = data["latitude"] as? String ?? ""
                      

                        return Post(id: .init(), longitudeVAR: longitudeVAR, latitudeVAR: latitudeVAR)
                    }
                }
            }

我正在尝试同时从两个用户那里获取信息,但我遇到的问题是这只会为一个用户或另一个用户绘制帖子信息(longitudeVar 和 latitudeVar)——而且它似乎是在user5@t.co 和 user6@t.co。有什么建议?如果这是一个基本问题或者我的代码写得不好,我也很抱歉 - 我只是想让它工作。谢谢!

【问题讨论】:

  • addSnapshotListener 异步工作。在一个循环中,您需要DispatchGroup。如果您实际上不需要索引,请不要在 Swift 中使用那些 stone-age-loops
  • stone-age-loops @vadian 给了我一个很好的笑声。
  • 代码含糊不清,我们不知道您为什么要这样做。似乎您的所有用户都使用电子邮件地址作为 documentId 存储?如果用户更改他们的电子邮件地址,这将是一个问题,因为您必须更改整个数据库中对它的每个引用。更好的选择是将用户的 documentId 存储为他们的用户 uid,然后将他们的电子邮件地址存储为其中的一个字段。目标是读取两个不同用户的坐标吗?如果是这样,是否会有两个以上的用户(使用数组将用于 - 一个未知的#)?你能澄清一下吗?
  • 另外,如上所述,您不能以这种方式从 Firebase 函数中 return 数据,因为它们是异步的。但是,我也不知道实现 DispatchGroups 是最好的解决方案。需要更明确的问题才能做出决定。
  • @Jay 感谢 cmets - 我为缺乏清晰度表示歉意。每个用户都有一个他们关注的人员列表(在本例中为“user5@t.co”和“user6@t.co”)。我正在使用此代码来绘制有关这些用户帖子的数据以创建提要。由于用户可以关注/取消关注其他帐户,因此该数组可能会发生变化。回答您的问题:是的,目标是读取两个不同用户的坐标。就像现在一样,我的代码只会从一个用户或另一个用户那里读取坐标,而不是同时读取这两个用户的坐标。这些帮助有用?再次感谢您的回复。

标签: arrays swift firebase google-cloud-firestore


【解决方案1】:

如果你想循环数据库获取并将它们的返回协调到一个任务中,那么你应该使用DispatchGroup。这是一个非常简单的 API,它会简单地记录您对 Firestore 进行了多少次调用,并为您提供一个完成处理程序,以便在最终到达那么多返回时(在最后一个返回结束时)执行。

不要在这里使用快照监听器,因为它们是用于数据流的——你想要的只是一次性的文档抓取。如果有很多文档要解析并且它们相对较大,那么我会考虑使用后台队列,这样 UI 不会在这种情况下出现卡顿。

var posts = [Post]()
let dispatch = DispatchGroup() // instantiate dispatch group outside loop

for item in items {
    dispatch.enter() // enter on each iteration
    
    // make a get-documents request, don't add a continuously-updating snapshot listener
    db.collection("users").document(item).collection("posts").getDocuments { (querySnapshot, error) in
        if let documents = querySnapshot?.documents {
            // fill a local array, don't overwrite the target array with each user
            let userPosts = documents.map { QueryDocumentSnapshot -> Post in
                let longitudeVar = data["longitude"] as? String ?? ""
                let latitudeVar = data["latitude"] as? String ?? ""
                
                return Post(id: .init(), longitudeVAR: longitudeVAR, latitudeVAR: latitudeVAR)
            }
            
            self.posts.append(userPosts) // append local array to target array
        } else if let error = error {
            print(error)
        }
        
        dispatch.leave() // always leave, no matter what happened inside the iteration
    }
}

/* this is the completion handler of the dispatch group
 that is called when all of the enters have equaled all
 of the leaves */
dispatch.notify(queue: .main) {
    self.tableView.reloadData() // or whatever
}

【讨论】:

  • 感谢您的评论-这样做很有意义。我尝试了您的代码,将数据附加到目标数组时仍然遇到同样的问题;它只是从一个项目中检索数据——而不是两个项目。有什么建议?再次感谢您的帮助!
  • 那你有数据问题。确保数据存在于数据库中,并且您正在获取正确的子集合。
猜你喜欢
  • 1970-01-01
  • 2016-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多