Как ждать завершения асинхронной задачи - Swift 4 - PullRequest
0 голосов
/ 10 мая 2018

Мне нужно прочитать данные из базы данных Firebase и вставить данные в структуру, над которой я позже сделаю некоторые операции. Проблема, с которой я сталкиваюсь сейчас, заключается в том, что, поскольку Firebase управляет этими вещами асинхронно, когда я проверяю внутри структуры, она часто равна нулю и еще не заполнена данными.

Я знаю, что использовать значение за пределами асинхронного блока, как я на самом деле, неправильно, и что обратные вызовы могут быть использованы для решения моей проблемы. Я прочитал несколько примеров в Интернете, но я не могу понять, как реализовать их в своем коде.

Ради простоты, в приведенном ниже примере я загружаю только один объект из базы данных.

func fetchJSON(key: String) -> Void {
  var meal = Meal()
  let ref = rootRef.child(key)

  ref.observe(.value) { (snap: DataSnapshot) in   
      meal.firstMeal = snap.childSnapshot(forPath: "first").value as! String
      meal.secondMeal = snap.childSnapshot(forPath: "second").value as! String
      meal.thirdMeal = snap.childSnapshot(forPath: "third").value as! String         
    }

  self.meals.append(meal)
}

А вот как выглядит вызов функции:

fetchJSON(key: currentDate)

Может ли кто-нибудь помочь мне?

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Для Firebase вы также можете найти полезные обещания. Я использую библиотеку PromiseKit , и она прекрасно работает.

Вы можете сделать что-то вроде этого:

fetchJSON(key: currentDate).done { meal in
    print(meal)
}

func fetchJSON(key: String) -> Promise<Meal> {
        let ref = rootRef.child(key)
        return Promise { seal in
            ref.observe(.value) { (snap: DataSnapshot) in
                guard let firstMeal = snap.childSnapshot(forPath: "first").value as! String,
                      let secondMeal = snap.childSnapshot(forPath: "second").value as! String,
                      let thirdMeal = snap.childSnapshot(forPath: "third").value as! String {
                        let meal = Meal(firstMeal: firstMeal, 
                                        secondMeal: secondMeal, 
                                        thirdMeal: thirdMeal)
                            seal.fulfill(meal)
                    }
                }
            }
        }
0 голосов
/ 10 мая 2018

Вы можете использовать завершенииHandler , сначала объявить typealias в вашем классе

typealias completion = (_ isFinished:Bool) -> Void

затем добавьте завершениеHandler к вашей функции:

func fetchJSON(key: String, completionHandler: @escaping completion){
    var meal = Meal()
    let ref = rootRef.child(key)

    ref.observe(.value) { (snap: DataSnapshot) in
        meal.firstMeal = snap.childSnapshot(forPath: "first").value as! String
        meal.secondMeal = snap.childSnapshot(forPath: "second").value as! String
        meal.thirdMeal = snap.childSnapshot(forPath: "third").value as! String
    }

    meals.append(meal)
    completionHandler(true)
}

затем вызовите вашу функцию следующим образом:

fetchJSON(key: currentDate, completionHandler: { (isFinished) in
    if isFinished {
        // do Somthing
    }
})
...