Блок завершения для вложенных запросов - PullRequest
0 голосов
/ 12 сентября 2018

Я пытаюсь построить методы с блоками завершения для вложенных запросов.Проблема заключается в том, что блок завершения перехватывается рано для родительских запросов (это означает, что дочерние запросы на самом деле еще не завершены).До сих пор я не нашел способа для дочернего запроса связаться с родительским запросом, кроме того, что я сделал в моем примере ниже (то есть подсчитать количество выполненных дочерних запросов и сравнить его с ожидаемой суммой.запросов).

Пример ниже работает с базой данных 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 голосов
/ 13 сентября 2018

Вот решение с использованием 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)
    }
}
...