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

问题描述 投票:0回答:1

我想在一个函数中运行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)
    }
ios google-cloud-firestore swift4.2
1个回答
1
投票

你需要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)
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.