Swift for 循环不等待 firestore 调用完成

Swift for loop not waiting for firestore call to complete

我知道 firestore 调用是异步的,这意味着这行不通:

    private func removeUserSavedMomentFromAllUsers(moment: StoryMoment, completion: @escaping () -> Void) {
        guard let savedByUIDs = moment.savedByUIDs else { return }
        guard let momentID = moment.id else { return }
        for id in savedByUIDs {
            self.userInfoCollection.document(id).collection("savedMedias").document(momentID).delete { error in
                if let error = error {
                    print("Error removing user saved moment from UID: \(error)")
                }
            }
        }
    }

因为循环将在删除调用完成之前继续(与获取请求相同)。我过去曾使用调度组来解决这个问题。这是一个工作示例:

    private func removeUserSavedMomentFromAllUsers(moment: StoryMoment, completion: @escaping () -> Void) {
        guard let savedByUIDs = moment.savedByUIDs else { return }
        guard let momentID = moment.id else { return }
        let disSemaphore = DispatchSemaphore(value: 0)
        let dispatchQueue = DispatchQueue(label: "group 1")
        
        dispatchQueue.async {
            for id in savedByUIDs {
                self.userInfoCollection.document(id).collection("savedMedias").document(momentID).delete { error in
                    if let error = error {
                        print("Error removing user saved moment from UID: \(error)")
                    } else {
                        disSemaphore.signal()
                    }
                }
                disSemaphore.wait()
            }
        }
    }

但是那些在后台线程上完成所有工作。 我的问题是:如何在调用 firebase docs 的 for 循环中使用 async/await?

问题第一部分中的代码确实有效 - 并且适用于一小部分数据。但是,通常建议不要在紧密循环中调用 Firebase 函数。

虽然问题提到了 DispatchQueues,但我们将 DispatchGroups 与 .enter 和 .leave 一起使用,因为它非常干净。

给定一个 Firebase 结构

sample_data
   a
      key: "value"
   b
      key: "value"
   c
      key: "value"
   d
      key: "value"
   e
      key: "value"
   f
      key: "value"

假设我们要删除 d、e 和 f 文档。这是代码

func dispatchGroupDelete() {
    let documentsToDelete = ["d", "e", "f"]
    let collection = self.db.collection("sample_data") //self.db points to my Firestore
    let group = DispatchGroup()
    
    for docId in documentsToDelete {
        group.enter()
        let docToDelete = collection.document(docId)
        docToDelete.delete()
        group.leave()
    }
}

虽然此答案不使用 async/await,但此用例可能不需要这些

如果你想使用 async/await 你试试这样做

let documentsToDelete = ["d", "e", "f"]
let collection = self.db.collection("sample_data")

for docId in documentsToDelete {
    let docToDelete = collection.document(docId)
    Task {
        do {
            try await docToDelete.delete()
        } catch {
            print("oops")
        }
    }
}