Ответ
DispatchGroup — это механизм GCD для синхронизации группы асинхронных или параллельных задач. Он позволяет отслеживать завершение произвольного количества задач и выполнить финальный блок кода, когда все они будут закончены.
Основные методы:
enter(): Увеличивает внутренний счетчик группы (начало задачи).leave(): Уменьшает счетчик (завершение задачи).notify(queue:execute:): Запланировать блок кода, который выполнится, когда счетчик станет равен нулю.wait(): Синхронно блокирует текущий поток до завершения всех задач группы (использовать с осторожностью).
Типичный use case: Загрузка данных из нескольких источников.
let imageGroup = DispatchGroup()
var downloadedImages: [UIImage] = []
// Задача 1: Загрузка аватара
imageGroup.enter()
networkService.loadAvatar { image in
downloadedImages.append(image)
imageGroup.leave()
}
// Задача 2: Загрузка обложки
imageGroup.enter()
networkService.loadCover { image in
downloadedImages.append(image)
imageGroup.leave()
}
// Действие после завершения ВСЕХ загрузок
imageGroup.notify(queue: .main) {
// Все изображения загружены, счетчик = 0
self.updateUI(with: downloadedImages)
print("Все изображения готовы")
}
// Основной поток не блокируется.
Ключевые моменты:
- Каждый
enter()должен быть сбалансирован соответствующимleave(). notify()— это асинхронный метод, он не блокирует вызывающий поток.- Идеально подходит для агрегации результатов нескольких независимых асинхронных операций.
Ответ 18+ 🔞
А, ну вот, смотри, опять эти ваши группы диспетчерские, блядь. DispatchGroup, сука. Это ж как будто ты в армии командируешь отделением, а они все по кустам разбежались, и тебе надо понять, когда они все, биздюны, обратно приползут, чтобы дальше маршировать.
Короче, это такая штука, чтобы синхронизировать кучу асинхронных дел. Представь, ты отправил пять запросов на сервер, и тебе надо дождаться, пока все пять, блядь, ответят, и только потом UI обновить. Вот для этого он и есть.
Основные команды, которые у него есть:
enter(): Это ты как бы говоришь: «Так, блядь, ещё один солдат ушёл в самоволку, за ним следим!». Внутренний счётчик увеличивается.leave(): А это когда солдат вернулся, весь в соплях, и говорит: «Я тут». Счётчик уменьшается.notify(queue:execute:): Это твоя команда, которую ты даёшь заранее: «Ребята, как только все вернутся — сразу на тусовку!». Этот блок выполнится, когда счётчик станет ноль.wait(): Это самый жёсткий метод, ёпта. Ты просто встаёшь и говоришь: «Я тут постою, пока все не придут». И текущий поток замирает нахуй, пока все задачи не завершатся. Использовать осторожно, а то зафризишь всё.
Типичная история: качаешь картинки с разных мест.
let imageGroup = DispatchGroup()
var downloadedImages: [UIImage] = []
// Задача 1: Качаем аватарку
imageGroup.enter() // Говорим: "Так, первая картинка пошла качаться, следим!"
networkService.loadAvatar { image in
downloadedImages.append(image)
imageGroup.leave() // Говорим: "Всё, эта пришла, можно вычёркивать!"
}
// Задача 2: Качаем обложку
imageGroup.enter() // "Так, вторая тоже ушла в сеть!"
networkService.loadCover { image in
downloadedImages.append(image)
imageGroup.leave() // И эта вернулась!
}
// И вот самое важное — что делать, когда ВСЕ наконец-то приползли?
imageGroup.notify(queue: .main) {
// Опа, счётчик ноль! Все картинки в массиве downloadedImages.
self.updateUI(with: downloadedImages)
print("Ну наконец-то, все изображения готовы, можно людей радовать!")
}
// И главное — основной поток тут не тормозит, он свободен, пока эти все там качаются.
Что важно помнить, чтобы не обосраться:
- На каждый
enter()должен быть свойleave(). Иначе счётчик не обнулится, и твойnotifyникогда не сработает, будешь ждать как лох. notify()— он асинхронный, умный. Он не будет тебя тут держать, он просто поставит напоминалку и пошёл дальше.- Идеальная вещь, когда тебе надо собрать результаты кучи независимых операций в одну кучу и потом что-то с ней сделать. Просто красота, а не инструмент.