Я делаю несколько вызовов API подряд, и когда я, наконец, нажимаю на свой следующий контроллер представления, мои данные полностью пусты из моей базовой модели данных. В ViewController A я сделал следующие запросы в этом порядке:
Api.verifyOtp(email, otp).continueWith { (task) -> Any? in
if task.succeed {
self.apiCallOne()
self.apiCallTwo()
self.apiCallThree()
self.apiCallFour()
self.apiCallFive()
} else {
Hud.hide()
task.showError()
}
return nil
}
Теперь все эти вызовы выполняются асинхронно. Однако последний метод, который является self.apiCallFive(), — это метод, который подталкивает к ViewController B. Вот звонок:
Api.apiCallFive().continueOnSuccessWith { (task) -> Any? in
Hud.hide()
if task.succeed {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewB storyboard.instantiateViewController(withIdentifier: "ViewControllerB" self.navigationController?.pushViewController(viewB, animated: true)
}
Я предполагаю, что, поскольку все эти запросы выполняются асинхронно, нет никакой гарантии, какой вызов завершится первым. Таким образом, apiCallFive() отправляет и загружает ViewController B до того, как другие смогут закончить. Как я могу сделать так, чтобы следующее представление не загружалось и не перенаправлялось до тех пор, пока все задачи не будут выполнены?
Спасибо!
Да, они встроены в запросы API. После того, как вызов завершил получение данных, объект создается и сохраняется в основных данных.
вы получаете уведомление, когда другой вызов API завершен?
Каким бы ни было решение, убедитесь, что вы не зависаете навсегда, если какой-либо из вызовов не работает.





Я столкнулся с той же проблемой. Исправьте это, используя DispatchGroup.
Код:
Определить как property
let APIGroup = DispatchGroup()
Выполните приведенный ниже код при запуске любого вызова API.
APIGroup.enter()
Выполните приведенный ниже код, когда любой вызов API завершен.
downloadGroup.leave()
Блокировать уведомления:
APIGroup.notify(queue: DispatchQueue.main) {
print("All APIs called successfully: Perform required operation")
}
Нет необходимости управлять каким-либо счетчиком или другими переменными. notify автоматически блокировать вызов, когда все задачи выполнены успешно.
What’s really important here is the enter-leave pairs. You have to be very careful and make sure that you leave the group. It would be easy to introduce a bug in the code above. Let’s say that we didn’t leave the group in that guard statement above, just before the return. If the API called failed, or the JSON was malformed, the number of groups> entries would not match the number of leaves. So the group completion handler would never get called. If you’re calling this method from the UI and displaying an activity indicator while your networking requests are running, you would never get a callback from the method, and you would keep on spinning ?
Матерь Божья, это прекрасное решение. Итак, я полагаю, что было бы лучше, если бы операция не удалась, я мог бы либо отобразить сообщение, уведомляющее пользователя о том, что он должен проверить свою сеть, либо любое другое сообщение об ошибке и повторить попытку позже? Кроме того, остановите вращение спиннера;)
@butter_baby Рад слышать. Удачного кодирования :)
Чтобы решить эту проблему, вам нужен способ получать уведомления о завершении каждого вызова. Самый простой способ сделать это — использовать блоки завершения для каждого вызова.
func apiCall(completion: @escaping () -> Void) {
....
}
После добавления блоков завершения к вызовам API ваши блоки могут выглядеть так:
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
apiCallOne {
dispatchGroup.leave()
}
dispatchGroup.enter()
apiCallTwo {
dispatchGroup.leave()
}
...
dispatchGroup.enter()
apiCallN {
dispatchGroup.leave()
}
dispatchGroup.wait(timeout: Constants.timeout)
Имейте в виду, что оператор wait заблокирует поток, в котором вы его вызываете, пока не будут выполнены все операторы leave(), поэтому будьте осторожны, чтобы не попасть в тупик.
Ах, отлично. На самом деле я вызываю большинство из них из одного класса API, и было бы нецелесообразно вводить группу диспетчеризации внутри этих методов, поскольку они также используются в другом месте моего проекта. Значит, безопасно вызывать dispatchGroup.enter() вне метода, а затем просто dispatchGroup.leave() внутри обработчика завершения?
Да, звонить им, как я показал выше, должно быть нормально. Хотя не уверен, что полностью понял ваш вопрос.
Я предполагаю, что эти вызовы API также делают что-то вроде записи результатов вызова API в основные данные?