OperationQueue — що це таке, Operation і управління завданнями

Автор: IT Sectr Опубліковано: 2026-03-16 Час читання: 8 хв

OperationQueue — це високорівнева черга завдань в iOS та macOS, побудована поверх Grand Central Dispatch. За даними Apple Developer Documentation, 2026, OperationQueue керує екземплярами Operation — об'єктами, які інкапсулюють одиницю роботи. На відміну від DispatchQueue, OperationQueue підтримує залежності між операціями, пріоритети, KVO-спостереження та скасування запущених завдань. OperationQueue автоматично керує пулом потоків, розподіляючи операції по доступних ресурсах системи.

Головне

  • OperationQueue — високорівнева черга з підтримкою залежностей між операціями
  • Operation — абстрактний клас для інкапсуляції одиниці роботи зі станом
  • BlockOperation — спрощена реалізація Operation для одного блоку коду
  • Залежності визначають порядок виконання: операція B запускається після A
  • Скасування операцій підтримується через KVO-сумісну властивість isCancelled

Що таке OperationQueue та Operation

OperationQueue — це клас із фреймворку Foundation, який керує виконанням об'єктів Operation. На відміну від DispatchQueue, OperationQueue не потребує явного вказання serial або concurrent режиму — кількість одночасно виконуваних операцій регулюється властивістю maxConcurrentOperationCount. Значення 1 перетворює чергу на послідовну, будь-яке інше — на конкурентну.

Operation — абстрактний клас, що представляє одиницю роботи. Кожна операція має стан: ready, executing, finished або cancelled. Стани сумісні з KVO (Key-Value Observing), що дозволяє реагувати на зміни — наприклад, оновлювати інтерфейс при завершенні операції. Operation автоматично керує прапорцями isExecuting та isFinished.

За даними Apple (2026), OperationQueue використовує GCD всередині, але додає функціональність, недоступну в DispatchQueue: залежності, пріоритети та скасування операцій. Якщо додаток переходить у фоновий режим, OperationQueue призупиняє виконання, а при поверненні — відновлює. OperationQueue також автоматично враховує кількість ядер процесора та вибирає оптимальну кількість потоків.

Життєвий цикл Operation

Кожна операція проходить через чотири стани: pending (очікування), ready (готова до запуску), executing (виконується) та finished (завершена). Стан cancelled може настати на будь-якому етапі до завершення. Переходи між станами відстежуються через KVO — це основа для реактивного оновлення інтерфейсу. OperationQueue автоматично видаляє завершені операції з черги та повідомляє залежні операції про те, що їхній prerequisite виконано, запускаючи їхнє виконання.

Operation та BlockOperation: реалізація завдань

Operation — абстрактний клас, що потребує перевизначення методу main() або start(). У методі main() розміщується код завдання, а стан isExecuting та isFinished керуються автоматично. Для асинхронних операцій потрібно перевизначити start() та вручну керувати прапорцями стану.

BlockOperation — конкретна реалізація Operation, що виконує один або кілька блоків коду. BlockOperation стає конкурентною, якщо додати в неї кілька блоків через addExecutionBlock(). Завершується операція лише після виконання всіх доданих блоків. BlockOperation — зручна альтернатива для простих завдань без успадкування.

ХарактеристикаOperationBlockOperation
Тип класуАбстрактнийКонкретний
УспадкуванняПотрібнеНе потрібне
АсинхронністьРучне керування KVOАвтоматичне
Блоків кодуОдин в main()Один або кілька
ЗастосуванняСкладні завдання зі станомПрості одноразові завдання
Підходить дляЗалежності, скасування, прогресШвидкі блоки, завершення
Пам'ятьВища через KVO та станМінімальна, легковага

Створення власної Operation

Для створення кастомної операції успадкуйте від Operation та перевизначте main(). Всередині перевіряйте прапорець isCancelled перед дорогими операціями, щоб забезпечити швидке скасування. Це критично для завантаження великих файлів або пакетної обробки даних. Вибір між Operation та BlockOperation залежить від складності завдання: для простих одноразових дій достатньо BlockOperation, для логіки, що перевикористовується, зі станом — успадкування від Operation.

Залежності та пріоритети операцій

Залежності — ключова перевага OperationQueue перед DispatchQueue. Метод addDependency(_:) визначає, що операція B виконується лише після завершення операції A. Залежності утворюють directed acyclic graph (DAG): при додаванні циклічної залежності черга ігнорує її, і операції не запускаються.

Пріоритет операції задається властивістю queuePriority зі значеннями: .veryLow, .low, .normal, .high, .veryHigh. Пріоритет впливає на порядок запуску серед ready-операцій, але не скасовує залежності. OperationQueue спочатку враховує залежності, потім — пріоритет серед доступних операцій.

Практичний приклад залежностей

Типовий сценарій — завантаження даних профілю: спочатку завантажуємо користувача, потім на основі його id завантажуємо друзів та пости. Встановлення залежності між завантаженням користувача та завантаженням друзів гарантує коректний порядок без вкладених completion handler.

Обмеження паралелізму

Властивість maxConcurrentOperationCount обмежує кількість одночасно виконуваних операцій. Значення 1 створює послідовну чергу, значення за замовчуванням (NSOperationQueueDefaultMaxConcurrentOperationCount) — системно-оптимальне, що залежить від поточного навантаження пристрою. Правильне налаштування цього параметра запобігає надмірному споживанню ресурсів: для завантаження зображень достатньо 4–6 конкурентних операцій, для CPU-інтенсивних завдань — кількість ядер процесора.

OperationQueue vs DispatchQueue: порівняння

Вибір між OperationQueue та DispatchQueue залежить від складності завдання. DispatchQueue — легковаговий інструмент для простих async-викликів. OperationQueue — більш важке рішення для складних сценаріїв із безліччю взаємопов'язаних завдань. Apple рекомендує починати з DispatchQueue та переходити на OperationQueue лише при необхідності залежностей або скасування. Для більшості iOS-проектів комбінація обох інструментів дає оптимальний баланс продуктивності та гнучкості.

  • DispatchQueue — легка, швидка, без накладних витрат на об'єкти Operation
  • OperationQueue — підтримує залежності, скасування, KVO та пріоритети
  • DispatchQueue — ідеальна для простих async/asyncAfter завдань та синхронізації через serial
  • OperationQueue — незамінна при покрокових алгоритмах із послідовними етапами
  • DispatchQueue — інтеграція з Swift Concurrency (async/await) через Continuation

За даними Ray Wenderlich (2025), у великих iOS-проектах OperationQueue використовується для завантаження контенту з прогресом та скасуванням, а DispatchQueue — для всіх інших async-операцій. Співвідношення приблизно 20 до 80 на користь DispatchQueue.

Приклади коду з OperationQueue в Swift

Розглянемо три приклади: простий BlockOperation, кастомна Operation із залежностями та скасовувана операція для завантаження даних.

BlockOperation із завершенням

Найпростіший випадок — виконати блок на OperationQueue та обробити результат через completionBlock. Кожна Operation має вбудовану властивість completionBlock, що викликається після завершення main().

swift
let queue = OperationQueue()
let operation = BlockOperation()
operation.addExecutionBlock {
    let data = NetworkService.fetchData()
    OperationQueue.main.addOperation {
        self.updateUI(data)
    }
}
queue.addOperation(operation)

Залежності між операціями

Залежність гарантує, що parseOperation запуститься лише після завершення downloadOperation. Це усуває необхідність у вкладених callback.

swift
let download = BlockOperation { self.downloadJSON() }
let parse = BlockOperation { self.parseJSON() }
parse.addDependency(download)

let queue = OperationQueue()
queue.addOperations([download, parse], waitUntilFinished: false)

Скасовувана кастомна Operation

Перевизначте main() з періодичною перевіркою isCancelled. Це дозволяє негайно зупинити операцію при скасуванні, не чекаючи завершення дорогої операції.

swift
class ImageLoadOperation: Operation {
    override func main() {
        guard !self.isCancelled else { return }
        let image = self.downloadImage()
        guard !self.isCancelled else { return }
        OperationQueue.main.addOperation { self.display(image) }
    }
}

Скасування операцій та KVO-спостереження

Скасування операції встановлює прапорець isCancelled в true, але не зупиняє вже запущений метод main(). Код всередині main() повинен самостійно перевіряти isCancelled та завершуватися при необхідності. Це архітектурне рішення Apple — що дозволяє розробнику коректно звільнити ресурси при скасуванні.

KVO-спостереження за властивостями isFinished та isExecuting дозволяє реагувати на завершення операцій без explicit callback. OperationQueue автоматично видаляє завершені операції з черги, але вони зберігаються в пам'яті доти, доки на них є сильні посилання. KVO — основа для інтеграції OperationQueue з реактивними фреймворками на кшталт RxSwift або Combine.

Обробка скасування через KVO

Підписка на isCancelled через KVO дозволяє оновлювати інтерфейс при скасуванні операції — наприклад, показувати placeholder замість скасованого завантаження. Властивість isCancelled є KVO-сумісною, що робить її зручною для реактивних pipeline.

Найкращі практики роботи з OperationQueue

Не створюйте операції у великих кількостях — кожна Operation є окремим об'єктом у пам'яті. Якщо завдання коротке та не потребує залежностей, використовуйте DispatchQueue безпосередньо. OperationQueue виправдана для складних сценаріїв із явними залежностями, скасуванням та моніторингом прогресу.

Перевіряйте isCancelled перед дорогими операціями всередині методу main(). У випадках завантаження файлів або обробки зображень перевірка після кожного значущого кроку забезпечує швидкий відгук на скасування. Використовуйте if isCancelled { return } на початку main() та після кожної великої операції.

Правильно керуйте completionBlock. Властивість completionBlock операції викликається після завершення main(), навіть якщо операцію було скасовано. Перевіряйте isCancelled всередині completionBlock, щоб не оновлювати інтерфейс помилковими даними. OperationQueue.main — потокобезпечна черга для UI-операцій, аналогічна DispatchQueue.main.

Уникайте циклічних залежностей — вони призводять до того, що жодна з операцій у циклі ніколи не запуститься. OperationQueue не детектує цикли автоматично: якщо A залежить від B, а B залежить від A, обидві назавжди залишаться в стані ready. Плануйте граф залежностей заздалегідь.

Часто задавані питання

Чим OperationQueue відрізняється від DispatchQueue?

OperationQueue побудована поверх GCD та додає залежності, пріоритети, KVO та скасування операцій. DispatchQueue — більш легкий інструмент для простих async завдань без цих можливостей.

Як зробити чергу послідовною?

Встановіть властивість maxConcurrentOperationCount в 1. Це перетворює OperationQueue на послідовну чергу зі збереженням усіх переваг — залежностей, пріоритетів та скасування.

Чи можна скасувати запущену операцію?

Метод cancel() встановлює прапорець isCancelled, але не зупиняє виконуваний метод main(). Код операції повинен сам перевіряти isCancelled та завершуватися. Скасування працює лише для pending та ready операцій.

Коли варто використовувати Operation замість BlockOperation?

Операцію варто успадковувати, коли потрібне керування станом, асинхронність або перевикористання логіки. BlockOperation підходить для простих одноразових завдань без успадкування.

Чи блокує OperationQueue головний потік?

Ні, якщо не викликано метод waitUntilFinished з параметром true на головному потоці. Операції за замовчуванням виконуються на фонових потоках, а результат повертається через OperationQueue.main.

Підсумки

  • OperationQueue — високорівнева черга з залежностями, пріоритетами та скасуванням операцій
  • Operation — абстрактний клас для інкапсуляції роботи з KVO-сумісним станом
  • BlockOperation — спрощена реалізація для одного або кількох блоків коду
  • Залежності задають порядок виконання між операціями через граф без циклів
  • Скасування потребує ручної перевірки isCancelled всередині методу main() операції
  • maxConcurrentOperationCount = 1 перетворює чергу на послідовний режим
  • OperationQueue vs DispatchQueue — вибирайте OperationQueue лише при необхідності залежностей або KVO

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також