Каковы преимущества использования DispatchWorkItem в GCD?

«Каковы преимущества использования DispatchWorkItem в GCD?» — вопрос из категории Многопоточность, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

DispatchWorkItem инкапсулирует задачу для выполнения в GCD, предоставляя расширенный контроль.

Ключевые преимущества:

  1. Отмена задачи: Возможность отменить выполнение до его начала с помощью cancel().

    let workItem = DispatchWorkItem { print("Выполняется") }
    DispatchQueue.global().asyncAfter(deadline: .now() + 1.0, execute: workItem)
    workItem.cancel() // Задача не будет выполнена
  2. Уведомление о завершении: Метод notify(queue:execute:) позволяет выполнить completion handler.

    let backgroundItem = DispatchWorkItem { /* Тяжелая задача */ }
    backgroundItem.notify(queue: .main) {
        print("Задача завершена, обновляем UI")
    }
    DispatchQueue.global().async(execute: backgroundItem)
  3. Повторное использование: Один DispatchWorkItem можно выполнить несколько раз на разных очередях.

  4. Гибкое планирование: Легко комбинируется с asyncAfter для отложенного выполнения.

  5. Приоритет на уровне задачи: Можно задать QoS (Quality of Service) для конкретной задачи, а не всей очереди, с помощью DispatchWorkItem(qos:flags:block:).

  6. Синхронное ожидание: Метод wait() блокирует текущий поток до завершения работы (используйте с осторожностью).

  7. Проверка состояния: Свойства isCancelled и isExecuting позволяют отслеживать статус.

Практический пример:

// Создаем workItem с высоким приоритетом
let dataProcessingItem = DispatchWorkItem(qos: .userInitiated) {
    processLargeDataset()
}

// Настраиваем completion
dataProcessingItem.notify(queue: .main) {
    self.updateProgressView()
}

// Планируем выполнение с задержкой
DispatchQueue.global().asyncAfter(deadline: .now() + 0.5, execute: dataProcessingItem)

// Возможность отменить, если пользователь ушел с экрана
// dataProcessingItem.cancel()