Ответ
Преимущества DispatchGroup:
- Простая синхронизация асинхронных задач: Позволяет легко ожидать завершения группы независимых асинхронных операций (например, нескольких сетевых запросов, операций с файлами).
- Удобный API: Базовые методы
enter(),leave()иnotify(queue:)интуитивно понятны. - Гибкость уведомления: Метод
notify(queue:)позволяет указать очередь (например,.main), на которой выполнится completion-блок после завершения всех задач. - Возможность синхронного ожидания: Метод
wait()(использовать с осторожностью) блокирует текущий поток до завершения группы.
Недостатки и риски DispatchGroup:
- Риск дедлока или блокировки UI: Вызов
wait()на главной очереди (.main) приведет к гарантированному фризу интерфейса.wait()следует использовать только на фоновых очередях. - Обязательность баланса
enter()/leave(): Каждому вызовуenter()должен соответствовать вызовleave(). Несоблюдение этого правила приведет к тому, чтоnotifyникогда не сработает (илиwaitбудет ждать вечно). - Отсутствие встроенной отмены:
DispatchGroupне предоставляет механизма отмены уже вошедших в группу задач. Для отмены требуется использовать другие механизмы (например,DispatchWorkItemс флагом отмены). - Нет обработки ошибок: Группа лишь отслеживает факт завершения, но не передает результаты или ошибки из отдельных задач. Это нужно реализовывать отдельно.
Пример типичного использования:
let group = DispatchGroup()
var fetchedData: [Data] = []
let queue = DispatchQueue(label: "com.example.sync", attributes: .concurrent)
// Задача 1
group.enter()
fetchUserProfile { profile in
queue.async(flags: .barrier) { fetchedData.append(profile) }
group.leave()
}
// Задача 2
group.enter()
fetchUserOrders { orders in
queue.async(flags: .barrier) { fetchedData.append(orders) }
group.leave()
}
// Действие после завершения ВСЕХ задач
group.notify(queue: .main) {
print("Все данные загружены: (fetchedData.count) элементов")
self.updateUI(with: fetchedData)
}
// ОПАСНЫЙ ПРИМЕР (чего делать не стоит):
// group.wait() // Вызов на главном потоке заблокирует UI
Альтернативы: Для более сложных сценариев рассмотрите OperationQueue с зависимостями или async/await с TaskGroup (Swift Concurrency).