Что такое DispatchQoS в GCD?

Ответ

DispatchQoS (Quality of Service) — это система приоритетов в Grand Central Dispatch (GCD), которая указывает системе на важность задачи. Это помогает в планировании, управлении энергопотреблением и распределении ресурсов (CPU, I/O).

Основные классы QoS (от высшего к низшему приоритету):

Класс QoS Назначение Пример использования
.userInteractive Задачи, напрямую влияющие на UI, требующие мгновенного отклика. Анимации, обновление интерфейса в реальном времени.
.userInitiated Задачи, инициированные пользователем, которые должны завершиться быстро. Обработка нажатия кнопки, загрузка данных для отображения.
.default Стандартный приоритет (между .userInitiated и .utility). Используется по умолчанию, если QoS не указан.
.utility Длительные задачи, о ходе которых пользователь может быть проинформирован. Экспорт данных, загрузка контента, периодические обновления.
.background Задачи, невидимые для пользователя, время выполнения не критично. Индексация, синхронизация, предварительная загрузка.

Пример использования:

// Выполнение ресурсоемкой задачи с высоким приоритетом
DispatchQueue.global(qos: .userInitiated).async {
    let processedData = self.processLargeDataset()
    // Возврат на главный поток для обновления UI
    DispatchQueue.main.async {
        self.updateUI(with: processedData)
    }
}

Ответ 18+ 🔞

О, слушай, смотри, вот эта вся хуйня с QoS в GCD — это, блядь, как в армии погоны. Чтобы система понимала, какого хуя важнее: твоя анимация моргания кнопки или там какая-то индексация фоток с отпуска трёхлетней давности.

Короче, есть у нас, сука, пять главных пацанов, от самого важного до того, кому вообще похуй.

Главные шишки (от самого крутого до самого забитого):

Класс QoS Это кто такой, бля? Где его юзать, чтобы не выебали?
.userInteractive Это, блядь, полковник. Задачи, от которых напрямую ебёт интерфейс. Если они тормознут — пользователь сразу поймёт, что ты мудак. Анимации, скролл, любое обновление хуйни на экране в реальном времени.
.userInitiated Майор. Пользователь только что нажал на что-то и ждёт, сука, результата. Нельзя его заставлять пялиться в спиннер до второго пришествия. Нажал кнопку «Сохранить» — надо сохранить. Потянул, чтобы обновить ленту — надо загрузить.
.default Прапорщик. Ни то ни сё. Если ты ленивая жопа и не указал приоритет — система сама воткнёт этот. Не охуевший, но и не последний.
.utility Рядовой-контрактник. Делает какую-то долгую работу, о которой пользователь в курсе, но не дергается каждую секунду. Какая-нибудь конвертация видео, загрузка альбома, обновление погоды раз в час.
.background Дед, которого отправили чистить картошку на задворках части. Делает что-то втихую, пока все спят. Пользователь про это даже не знает. Синхронизация каких-то логов, предзагрузка данных «на потом», чистка кеша.

Ну и как этим, блядь, пользоваться? Да элементарно, ёпта!

// Допустим, пользователь ткнул кнопку, чтобы применить фильтр к фото.
// Это важно, значит юзаем .userInitiated, чтобы не тормозило.
DispatchQueue.global(qos: .userInitiated).async {
    // Всё, мы на фоне, можем ебашить ресурсоёмкую хуйню.
    let filteredImage = self.applyHeavyFilter(to: hugeImage)
    // Как только всё сделали — срочно на главный поток, обновлять UI!
    // Главный поток — это .userInteractive по умолчанию, царь-пушка.
    DispatchQueue.main.async {
        self.imageView.image = filteredImage
    }
}

Вот и вся магия, блядь. Главное — не путай: UI-обновления только на main.async, а всю тяжёлую работу скидывай на глобальные очереди с правильным QoS, чтобы система не начала хуярить батарею и процессор просто так, ебать её в сраку.