Ответ
Для синхронизации нескольких асинхронных операций в iOS используются следующие подходы:
1. DispatchGroup (GCD) Идеален для объединения задач, выполняющихся на разных очередях.
let group = DispatchGroup()
var results: [ResultType] = []
var errors: [Error] = []
// Запрос 1
group.enter()
networkService.fetchFirstData { result in
defer { group.leave() }
switch result {
case .success(let data): results.append(data)
case .failure(let error): errors.append(error)
}
}
// Запрос 2 и 3 аналогично...
// Обработка завершения всех задач
group.notify(queue: .main) {
if errors.isEmpty {
updateUI(with: results)
} else {
// Реализовать стратегию: показать частичные данные или общую ошибку
handlePartialResults(results, errors: errors)
}
}
2. TaskGroup (Swift Concurrency)
Современный способ с использованием async/await (Swift 5.5+).
Task {
async let firstData = networkService.fetchFirstData()
async let secondData = networkService.fetchSecondData()
async let thirdData = networkService.fetchThirdData()
do {
let allData = try await [firstData, secondData, thirdData]
await MainActor.run { updateUI(with: allData) }
} catch {
// Обработка ошибки (первой или агрегированной)
}
}
3. Combine Для реактивного подхода с использованием фреймворка Combine.
Publishers.Zip3(
networkService.fetchFirstDataPublisher(),
networkService.fetchSecondDataPublisher(),
networkService.fetchThirdDataPublisher()
)
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { completion in
// Обработка завершения/ошибки
}, receiveValue: { data1, data2, data3 in
updateUI(with: [data1, data2, data3])
})
.store(in: &cancellables)
Ключевые моменты:
- Обработка ошибок: Решите, нужно ли ждать успеха всех запросов или можно отобразить частичные данные.
- Прогресс: Для отображения общего прогресса можно использовать
DispatchGroupс счетчиком илиProgress. - Производительность: Запросы, не зависящие друг от друга, следует запускать параллельно, а не последовательно.