嵌套请求的完成块

时间:2018-09-12 14:35:55

标签: ios swift firebase request completion

我正在尝试为嵌套请求构建带有完成块的方法。问题在于,对于父级请求,完成块会提前捕获(这意味着子级请求尚未实际完成)。到目前为止,除了我在下面的示例中所做的事情之外,我还没有找到子请求与父请求进行通信的方法(该方法是计算子请求已完成的数量并将其与预期数量进行比较的请求)。

以下示例适用于Firestore数据库。想象一个用户有多个纸牌游戏(甲板),每个纸牌。非常感谢您为这样的情况建立更好的完成模块提供帮助:

func fetchCardsCount(uid: String, completion: @escaping (Int) -> ()) {
    let db = Firestore.firestore()


    var decksCount = Int()
    var cardsCount = Int()

    db.collection("users").document(uid).collection("decks").getDocuments { (deckSnapshot, err) in
        if let err = err {
            print("Error fetching decks for user: ", err)
        } else {
            guard let deckSnapshot = deckSnapshot else { return }

            deckSnapshot.documents.forEach({ (deck) in
                let dictionary = deck.data() as [String: Any]
                let deck = FSDeck(dictionary: dictionary)
                db.collection("users").document(uid).collection("decks").document(deck.deckId).collection("cards").getDocuments(completion: { (cardSnapshot, err) in
                    if let err = err {
                        print("Error fetching cards for deck: ", err)
                    } else {
                        guard let cardSnapshot = cardSnapshot else { return }
                        decksCount += 1
                        cardsCount += cardSnapshot.count

                        if decksCount == deckSnapshot.count {
                            completion(cardsCount)
                        }
                    }
                })
            })
        }
    }
}

1 个答案:

答案 0 :(得分:0)

以下是使用DispatchGroup的解决方案,该解决方案是在@meggar的帮助下找到的:

func fetchCardsCount(uid: String, completion: @escaping (Int) -> ()) {
    let db = Firestore.firestore()

    var cardsCount = Int()
    let group = DispatchGroup()

    group.enter()
    db.collection("users").document(uid).collection("decks").getDocuments { (deckSnapshot, err) in
        if let err = err {
            print("Error fetching decks for user: ", err)
        } else {
            guard let deckSnapshot = deckSnapshot else { return }

            deckSnapshot.documents.forEach({ (deck) in
                let dictionary = deck.data() as [String: Any]
                let deck = FSDeck(dictionary: dictionary)

                group.enter()
                db.collection("users").document(uid).collection("decks").document(deck.deckId).collection("cards").getDocuments(completion: { (cardSnapshot, err) in
                    if let err = err {
                        print("Error fetching cards for deck: ", err)
                    } else {
                        guard let cardSnapshot = cardSnapshot else { return }
                        cardsCount += cardSnapshot.count
                    }
                    group.leave()
                })
            })
        }
        group.leave()
    }

    group.notify(queue: .main) {
        completion(cardsCount)
    }
}