Когда использовать Grand Central Dispatch (GCD) в iOS?

Ответ

Grand Central Dispatch (GCD) — это низкоуровневый фреймворк для управления параллельным и асинхронным выполнением задач. Используйте его для:

  • Выполнения задач вне главного потока. Чтобы не блокировать UI.
    DispatchQueue.global(qos: .userInitiated).async {
        // Тяжелая задача (парсинг, вычисления)
        let result = processData()
        DispatchQueue.main.async {
            // Возврат результата в главный поток для обновления UI
            updateUI(with: result)
        }
    }
  • Планирования отложенного выполнения.
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
        // Выполнится через 0.5 секунды
    }
  • Синхронизации доступа к общим ресурсам с использованием сериальных очередей (DispatchQueue(label: "com.sync.queue")) или семафоров (DispatchSemaphore).
  • Группировки асинхронных задач с помощью DispatchGroup для ожидания их завершения.

Когда выбрать OperationQueue вместо GCD:

  • Нужны зависимости между задачами (operationB.addDependency(operationA)).
  • Требуется возможность отмены (operation.cancel()) или наблюдения за состоянием задачи.
  • Задачи можно инкапсулировать в переиспользуемый объект (BlockOperation или кастомный подкласс Operation).

GCD — это основа для простых и эффективных асинхронных операций.

Ответ 18+ 🔞

А, ну вот, смотри, подъехал наш старый знакомый — Grand Central Dispatch, или, как его в народе кличут, GCD. Это, блядь, такой низкоуровневый мужик, который командует парадом всех этих твоих асинхронных и параллельных тасок. Если по-простому — он решает, какую хуйню и в каком порядке выполнять, чтобы у тебя всё не легло в один прекрасный момент.

Зачем он, этот ёпта, вообще нужен?

  • Чтобы не ебать главный поток. Ну серьёзно, представь: ты в приложении кнопку нажимаешь, а оно вдруг задумалось на 5 секунд, потому что фотку в 4К обрабатывает. Пользователь сразу думает: «Приложение сдохло, нахуй». Вот чтобы такого не было, всю тяжёлую работу (типа парсинга JSON, вычислений, загрузки данных из сети) мы сваливаем на фоновые потоки.

    // Говорим: "Эй, система, дай-ка мне глобальную очередь для важных пользовательских дел"
    DispatchQueue.global(qos: .userInitiated).async {
        // И вот тут, в этой песочнице, делаем всю грязную работу
        let result = processData() // Тяжело, потно, но главному потоку похуй
        // А как закончили — кричим главному потоку: "Эй, братан, держи результат, обнови интерфейс!"
        DispatchQueue.main.async {
            updateUI(with: result)
        }
    }

    Главный поток спокоен, анимации плавные, пользователь доволен. Красота.

  • Чтобы сделать что-то попозже. «Напомни мне через полсекунды», — говоришь ты системе.

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
        // И через 0.5 секунды тебе напомнят. Точно. Как швейцарские часы, блядь.
    }
  • Чтобы не устроить драку за ресурсы. Представь, два потока одновременно лезут в один и тот же массив что-то писать. Это пиздец, а не race condition. Чтобы такого не было, используют либо сериальные очереди (все задачи выполняются строго по очереди, как в совке за колбасой), либо семафоры — такие суровые вышибалы, которые пускают к ресурсу только одного в момент времени.

  • Чтобы дождаться, пока куча асинхронных дел сделается. DispatchGroup — это как учительница в началке: «Дети, все построились? Все пришли? Все задание сделали? А теперь идём в столовую». Пока все задачи в группе не отрапортуют о завершении, дальше не двинемся.

А когда тогда брать OperationQueue?

Вот смотри, GCD — это как молоток. Универсально, мощно, но иногда им гвоздь забить — овердохуища мороки. OperationQueue — это уже типа шуруповёрт с насадками.

Берёшь OperationQueue, когда:

  • Задачи зависят друг от друга. Нужно сначала скачать данные, а только потом их распарсить. С GCD пришлось бы городить огород, а тут — operationB.addDependency(operationA), и всё, пизда.
  • Хочешь иметь право передумать. Запустил задачу, а пользователь уже ушёл с экрана. С GCD остановить задачу в процессе — та ещё головная боль. А в Operationoperation.cancel(), и можно спать спокойно (ну, почти). Ещё можно смотреть, в каком она состоянии: выполняется, отменена или уже всё.
  • Хочешь красивую, переиспользуемую упаковку. Можешь завернуть свою задачу в кастомный подкласс Operation и таскать его с собой, как чемоданчик с инструментами.

Короче, GCD — это фундамент, быстрый и жёсткий. А OperationQueue — надстройка для более сложных и управляемых сценариев. Выбирай по обстановке, а то так и до deadlock'а недалеко, ёпта.