如何在一个函数中 运行 2 个异步代码并转义它们?

How can I run 2 asynchrones code in one function and escape them?

我想运行一个函数中的2段异步代码然后转义。我想先下载 Reciter 信息,然后使用这些信息下载与 Reciter 关联的图像。我正在使用 Firestore。我尝试使用 DispatchQueue 和 DispatchGroup,但我无法弄清楚。我希望有人能帮助我:)

func getReciters(completion: @escaping (Bool) -> Void) {
        var reciters = [Reciter]()
            self.BASE_URL.collection(REF_RECITERS).getDocuments { (snapchot, error) in
                if let error = error {
                    debugPrint(error)
                    completion(false)
                    // TODO ADD UIALTERCONTROLLER MESSAGE
                    return
                }

                guard let snapchot = snapchot else { debugPrint("NO SNAPSHOT"); completion(false); return }

                for reciter in snapchot.documents {
                    let data = reciter.data()
                    let reciterName = data[REF_RECITER_NAME] as? String ?? "ERROR"
                    let numberOfSurahs = data[REF_NUMBER_OF_SURAHS] as? Int ?? 0

// **HERE I WANT TO DOWNLOAD THE IMAGES**
                    self.downloadImage(forDocumentID: reciter.documentID, completion: { (image) in
                        let reciter = Reciter(name: reciterName, image: nil, surahCount: numberOfSurahs, documentID: reciter.documentID)
                        reciters.append(reciter)
                    })
                }
            }
        UserDefaults.standard.saveReciters(reciters)
        completion(true)
    }

你需要DispatchGroup.

  • 在函数范围内声明一个DispatchGroup的实例。
  • 在循环之前异步块调用enter.
  • 在循环里面异步块调用的完成处理程序leave.
  • 循环调用后notify,所有异步任务完成后将执行闭包。

func getReciters(completion: @escaping (Bool) -> Void) {
    var reciters = [Reciter]()
    self.BASE_URL.collection(REF_RECITERS).getDocuments { (snapchot, error) in
        if let error = error {
            debugPrint(error)
            completion(false)
            // TODO ADD UIALTERCONTROLLER MESSAGE
            return
        }

        guard let snapchot = snapchot else { debugPrint("NO SNAPSHOT"); completion(false); return }
        let group = DispatchGroup()

        for reciter in snapchot.documents {
            let data = reciter.data()
            let reciterName = data[REF_RECITER_NAME] as? String ?? "ERROR"
            let numberOfSurahs = data[REF_NUMBER_OF_SURAHS] as? Int ?? 0
            group.enter()

            self.downloadImage(forDocumentID: reciter.documentID, completion: { (image) in
                let reciter = Reciter(name: reciterName, image: nil, surahCount: numberOfSurahs, documentID: reciter.documentID)
                reciters.append(reciter)
                group.leave()
            })
        }
        group.notify(queue: .main) {
            UserDefaults.standard.saveReciters(reciters)
            completion(true)
        }
    }
}