Ответ
DispatchWorkItem — это объектная обертка над замыканием (closure) в GCD, предоставляющая расширенный контроль над выполнением задачи: отмену, задержку, уведомление о завершении.
Ключевые возможности:
- Отмена задачи: Метод
cancel(). Отмененная задача не будет запущена, а если уже выполняется, может проверить свойствоisCancelled. - Задержка выполнения: Используется с
DispatchQueue.asyncAfter. - Синхронный запуск: Метод
perform()для немедленного выполнения в текущем потоке. - Уведомления: Можно установить обработчик завершения через
notify(queue:execute:).
Примеры использования:
1. Отмена отложенной задачи (поиск с debounce):
class SearchManager {
private var pendingSearchWorkItem: DispatchWorkItem?
func performSearch(query: String) {
// Отменяем предыдущий отложенный поиск
pendingSearchWorkItem?.cancel()
let newWorkItem = DispatchWorkItem { [weak self] in
self?.executeSearch(query: query)
}
pendingSearchWorkItem = newWorkItem
// Запускаем новый поиск через 0.3 секунды
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: newWorkItem)
}
}
2. Зависимости и уведомления:
let backgroundWorkItem = DispatchWorkItem { /* Тяжелая задача */ }
let completionWorkItem = DispatchWorkItem { print("Завершено") }
// Запустить completionWorkItem после backgroundWorkItem
backgroundWorkItem.notify(queue: .main, execute: completionWorkItem)
DispatchQueue.global().async(execute: backgroundWorkItem)
Преимущество перед простым замыканием: DispatchWorkItem инкапсулирует состояние и логику управления жизненным циклом задачи.
Ответ 18+ 🔞
Вот же ж, ну что за мрак, блядь! Смотри, сейчас объясню про эту штуку, которая выглядит как какая-то мартышлюшка, а на деле — просто пиздец как удобно.
DispatchWorkItem — это, по сути, твоё обычное замыкание, но в бронежилете и с пультом управления, ёпта. Взяли closure, завернули в объект, и теперь можно им вертеть как хочешь: отменять, откладывать, ставить в очередь на выполнение после другой задачи. Вообще, красота, а не хуйня.
Что эта бандура умеет, блядь:
- Отменить задачу нахуй: Есть метод
cancel(). Если задача ещё не стартанула — она и не стартанет. А если уже в процессе, то внутри неё можно проверитьisCancelledи аккуратно свернуть лавочку. - Задержать выполнение: Классика —
DispatchQueue.asyncAfter. Отправил задачу в будущее, как письмо с опозданием. - Запустить тут же, синхронно: Метод
perform()— хрясь, и выполняется прямо в текущем потоке, не отходя от кассы. - Сообщать о своей кончине: Через
notify(queue:execute:)можно прицепить другую задачку, которая запустится, когда первая благополучно сдохнет.
Смотри, как это в деле выглядит, на двух пальцах:
1. Умный поиск, который не дрочит сервер каждое нажатие клавиши (debounce):
class SearchManager {
private var pendingSearchWorkItem: DispatchWorkItem?
func performSearch(query: String) {
// А ну-ка отмена, старая задача! Хуй тебе, а не поиск.
pendingSearchWorkItem?.cancel()
let newWorkItem = DispatchWorkItem { [weak self] in
self?.executeSearch(query: query)
}
pendingSearchWorkItem = newWorkItem
// А новую запустим через 0.3 секунды, если юзер уже успокоился.
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: newWorkItem)
}
}
Вот и всё, волнение ебать! Раньше юзер вводил "к", "ко", "кот" — и три запроса летело. А теперь только один, последний. Умно, да? Не то что некоторые.
2. Задачи-паразиты, которые ждут друг друга (уведомления):
let backgroundWorkItem = DispatchWorkItem { /* Какая-нибудь тяжёлая хуйня, типа обработки фото */ }
let completionWorkItem = DispatchWorkItem { print("Всё, готово, можно пить чай") }
// Говорим completionWorkItem: "Слушай сюда, дружок. Ты стартуешь только после того, как backgroundWorkItem закончит свою волынку".
backgroundWorkItem.notify(queue: .main, execute: completionWorkItem)
// И отправляем тяжёлую задачу в бэкграунд.
DispatchQueue.global().async(execute: backgroundWorkItem)
И понеслась! Первая задача пашет, вторая терпеливо ждёт на главной очереди своего звёздного часа. Красота!
Так в чём же, блядь, соль? А соль в том, что простое замыкание — это как голый мужик на морозе. А DispatchWorkItem — это тот же мужик, но в тёплой куртке, с документами и навигатором в кармане. Он инкапсулирует в себе всю логику управления: состояние, отмену, зависимости. Не нужно городить костыли из флагов и таймеров — взял готовый инструмент и поехал. Пизда с ушами, а не решение!