Необходимо получить сумму корзины покупок после серии поисков цены getDocument - PullRequest
0 голосов
/ 14 октября 2019

Я пытаюсь получить общую сумму корзины покупок в Firestore, выполняя серию циклических вызовов для расчета суммы товаров в корзине.

Корзина покупок хранится в таблицес именем carts и представление после появления помещается в словарь в приложении cartCache, типа [String: Int]? где ключ - это UID для элемента, а значение - количество элемента. Однако цена предмета хранится в другой коллекции под названием items . Я хочу вычислить сумму только тогда, когда представление появляется или исчезает, а затем сделать так, чтобы оно отображалось в UILabel.

Таким образом, чтобы получить сумму и сообщить о ней пользователю (путем изменения метки илизаписывая его в корзину), мне нужно перебрать каждый элемент в моей корзине и получить цену с помощью вызова API getDocument (завершение :). Однако это означает, что вычисление суммы является асинхронным, что не обязательно является проблемой, но я не уверен, как передать обработчик завершения в цикл for. Есть ли более простой способ сделать это?

for item in self.cartCache!.keys
      {
        let doc = self.itemCollectionRef.document(item).getDocument
        {
          (itemDocument, error) in
          {
            guard let itemDocument = itemDocument, itemDocument.exists else {return}
            sum += itemDocument.data()!["price"] as! Int
          }
        }
      }

//Do something with sum (no guarantee at this point that sum is actually calculated, how do I add
//a completion handler to a for loop or obtain multiple field's values at once?

1 Ответ

2 голосов
/ 14 октября 2019

Что вам нужно использовать, это DispatchGroup. DispatchGroup s позволяют вам запускать несколько асинхронных функций одновременно и иметь один «обработчик завершения», который вызывается после завершения каждой асинхронной функции. Некоторый базовый код выглядит примерно так:

//Create your dispatch group. This is going to manage all of your asynchronous tasks and run some code when they complete
let group = DispatchGroup()

for x in array {
    //Call enter before the asynchronous function
    group.enter()
    asnynchronousFunction(completion: {
        //Call leave once the asynchronous function completes
        group.leave()
    })
}

group.notify(queue: .main, execute: {
    //Inside of group.notify, run whatever code you want to run upon completion of all asynchronous functions.
    //group.notify is your "completion handler"
})

Итак, для вашего примера это будет выглядеть примерно так:

let group = DispatchGroup()
for item in self.cartCache!.keys
      {
        group.enter()
        let doc = self.itemCollectionRef.document(item).getDocument
        {
          (itemDocument, error) in
          {
            guard let itemDocument = itemDocument, itemDocument.exists else {return}
            sum += itemDocument.data()!["price"] as! Int
            group.leave()
          }
        }
      }

group.notify(queue: .main, execute: { 
    //All of your asynchronous functions have completed. You are ready to move on
})

Источник: https://developer.apple.com/documentation/dispatch/dispatchgroup

Более подробно: https://www.raywenderlich.com/5371-grand-central-dispatch-tutorial-for-swift-4-part-2-2#toc-anchor-002

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...