#ios #swift #async-await #concurrency #swift5.5
Вопрос:
Я рефакторингую/переписываю некоторый код в устаревшем приложении, в котором (иногда) выполняется длительный запрос. Пользовательский контроллер представления используется для отображения хода выполнения, и когда запрос завершен, отображается другой контроллер представления для результата.
Текущий код представляет VC хода выполнения, затем запускает задачу для запроса, и когда запрос завершен, он представляет результат VC. Проблема в том, что индикатор выполнения отклоняется «автоматически», когда задача запроса отправляет уведомление об успешном выполнении через Центр уведомлений. Излишне говорить, что это не очень стабильно, и много раз VC прогресса не отклоняется вовремя до представления результата VC, что приводит к печати строгого журнала с iOS и отсутствию результата VC.
Чтобы избежать больших изменений в коде (на данный момент) Я изменил его, чтобы индикатор прогресса полностью контролировался из контекста, в котором он представлен. Но мне все равно нужно дождаться, пока он будет полностью представлен, прежде чем его можно будет отклонить, и это необходимо синхронизировать с запросом, который может выполняться быстрее, чем время презентации.
Подводя итог, скажу, что это моя текущая идея, но я не очень доволен тем, что у меня есть отдельная задача только для синхронизации. В «нормальной» среде параллелизма я бы использовал двоичный семафор или что-то подобное, есть ли более чистое решение в Swift? Я ищу способ сообщить Задаче о том, что был вызван обработчик завершения для present()
метода -.
let t = Task { // Wait longer than present(animated: true) time try await Task.sleep(nanoseconds: 10_000_000_000) } let controller = UIAlertController(title: "Progress", message: nil, preferredStyle: .alert) self.present(controller, animated: true, completion: { t.cancel() }) Task { // Perform work that may take less or more time than presentation try await Task.sleep(nanoseconds: 10_000_000) // Wait until alert is fully presented (no wait if work time was long enough) let _ = await t.result // Cleanup controller.dismiss(animated: true, completion: nil) // Present work result view controller // ... }
Комментарии:
1. Я думаю, что здесь необходима дополнительная информация, но, возможно, вы могли бы использовать продолжение и сохранить его в контроллере представления назначения.