Стандартный шаблон - notify
с DispatchGroup
, а затем используйте обработчик завершения для асинхронного уведомления вызывающей стороны о результате:
func fetchAll(completion: @escaping (Result<[Double], Error>) -> Void) {
let group = DispatchGroup()
var results: [Double] = []
var errors: [Error] = []
for item in lookupItems {
group.enter() // enter before request
AF.request(item).validate().responseJSON { response in
defer { group.leave() } // leave when this closure is done
switch response.result {
case .failure(let error):
errors.append(error)
case .success(let value):
let result = ...
results.append(result)
}
}
}
group.notify(queue: .main) {
if let error = errors.first { // I don’t know what you want to do if there were multiple errors, so for now I’ll just grab the first one
completion(.failure(error))
} else {
completion(.success(results))
}
}
}
И тогда вы будете использовать его следующим образом:
fetchAll { result in
switch result {
case .failure(let error):
print(error)
case .success(let values):
print(values)
}
}
Теперь я не смог перепроектировать то, что вы пытались сделать (похоже, вы обновляете self.arrayData[0]
на каждой итерации!), Поэтому я просто возвратил массив Double
, Но вы, очевидно, можете изменить тип results
и параметр закрытия completion
, чтобы он соответствовал тому, что имеет значение в вашем случае.
Но не заблудитесь в деталях приведенного выше примера, но достаточно просто сосредоточиться на нескольких ключевых наблюдениях:
- Закрытие обработчика завершения подачи для вызова, когда все запросы выполнены.
- Используйте
DispatchGroup
, чтобы отслеживать, когда все запросы готово. - Предоставьте
notify
закрытие для вашего DispatchGroup
, который будет вызываться, когда все вызовы group.enter()
компенсируются соответствующими group.leave()
вызовами. - Более тонкое наблюдение Вы должны воздерживаться от обновления свойств из блока
responseJSON
. В вашем асинхронном коде вы действительно хотите ограничить свое взаимодействие локальными переменными, если это вообще возможно. Передайте результат обратно в закрытие completion
(и вызывающая сторона может обновить модель и пользовательский интерфейс по своему усмотрению).