OperationQueue је високопоставен опашка задачи у iOS и macOS-у, изграден изнад Grand Central Dispatch-а. Според Apple Developer Documentation, 2026, OperationQueue управлява инстанции Operation — обекти који капсулират единица посла. За разлика от DispatchQueue-а, OperationQueue поддържа зависимости между операција, приоритети, KVO наблюдение и отмяна стартирани задачи. OperationQueue автоматично управлява пул от нишки, разпределяйки операције према наличните системни ресурси.
Основни
OperationQueue је класа из Framework-а Foundation која управлява извршавањем објеката Operation. За разлика от DispatchQueue-а, OperationQueue не захтева експлицитно навођење serial или concurrent режима — број истовремено извршаваних операција се регулише свойством maxConcurrentOperationCount. Вопашканост 1 претвара опашка у sequential, било која друга вопашканост — у concurrent.
Operation је абстрактен клас која попашкаставља единица посла. Свака операција има стање: ready, executing, finished или cancelled. Стања су компатибилна са KVO (Key-Value Observing), што омогућава реакцију на промене — на пример, ажурирање UI-ја по завршетку операције. Operation автоматично управлява заставицама isExecuting и isFinished.
Според Apple-у (2026), OperationQueue користи GCD испод хаубе, али додаје функционалности недоступне у DispatchQueue-у: зависности, приоритети и отмяна операција. Ако апликација пређе у позадински режим, OperationQueue зауставља извршавање, а по повратку — наставља. OperationQueue такође автоматично узима у обзир број језгара процесора и бира оптималан број нити.
Свака операција пролази кроз четири стања: pending (чекање), ready (спремна за покретање), executing (извршава се) и finished (завршена). Стање cancelled може наступити у било којој фази пре завршетка. Прелази између стања се прате кроз KVO — ово је основа за реактивно ажурирање UI-ја. OperationQueue автоматично уклања завршене операције из опашкаа и обавештава зависне операције да је њихов попашкауслов испуњен, покрећући њихово извршавање.
Operation је абстрактен клас која захтева преоптерећивање методе main() или start(). У методи main() се поставља код задатка, а стање isExecuting и isFinished се управлява автоматично. За асинхроне операције је потребно преоптеретити start() и ручно управлявати заставицама стања.
BlockOperation је конкретна имплементация Operation-а која извршава један или више блокова кода. BlockOperation постаје concurrent ако јој се дода више блокова путем addExecutionBlock(). Операција се завршава тек након изпълнение свих додатих блокова. BlockOperation је згодна алтернатива за једноставне задатке без наслеђивања.
| Карактеристика | Operation | BlockOperation |
|---|---|---|
| Тип класе | Апстрактна | Конкретна |
| Наслеђивање | Потребно | Није потребно |
| Асинхроност | Ручно управлявање KVO | Аутоматско |
| Блокова кода | Један у main() | Један или више |
| Примена | Сложени задаци са стањем | Једноставни једнократни задаци |
| Погодно за | Зависности, отмяна, напопашкаак | Брзи блокови, completion |
| Меморија | Већа због KVO и стања | Минимална, лагана |
За креирање прилагођене операције наследите 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 ствара sequential опашка, подразумевана вопашканост (NSOperationQueueDefaultMaxConcurrentOperationCount) — системски оптимална, зависна од тренутног оптерећења уређаја. Правилно подешавање овог параметра спречава прекомерну потрошњу ресурса: за учитавање слика довољно је 4-6 concurrent операција, за CPU-интензивне задатке — број језгара процесора.
Избор између OperationQueue-а и DispatchQueue-а зависи од сложености задатка. DispatchQueue је лагани алат за једноставне async позиве. OperationQueue је теже решење за сложене сценарије са више међусобно повезаних задачи. Apple препоручује почети са DispatchQueue-ом и прећи на OperationQueue само када су потребне зависности или отмяна. За већину iOS пројеката комбинација оба алата даје оптималан баланс перформанси и флексибилности.
Според Ray Wenderlich-у (2025), у великим iOS пројектима OperationQueue се користи за учитавање садржаја са напретком и отмянам, а DispatchQueue — за све остале async операције. Однос је приближно 20 према 80 у корист DispatchQueue-а.
Размотримо три примера: једноставан BlockOperation, прилагођену Operation са зависностима и операцију која се може отказати за учитавање података.
Најједноставнији случај — извршите блок на OperationQueue-у и обрадите резултат кроз completionBlock. Свака Operation има уграђено свойство completionBlock, које се позива након завршетка main().
let queue = OperationQueue()
let operation = BlockOperation()
operation.addExecutionBlock {
let data = NetworkService.fetchData()
OperationQueue.main.addOperation {
self.updateUI(data)
}
}
queue.addOperation(operation)
Зависност гарантује да parseOperation почиње тек након завршетка downloadOperation. Ово елиминише потребу за угњежденим callback-овима.
let download = BlockOperation { self.downloadJSON() }
let parse = BlockOperation { self.parseJSON() }
parse.addDependency(download)
let queue = OperationQueue()
queue.addOperations([download, parse], waitUntilFinished: false)
Преоптеретите main() са периодичном провером isCancelled. Ово омогућава тренутно заустављање операције при отказивању, без чекања на завршетак скупе операције.
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) }
}
}
Отказивање операције поставља заставицу isCancelled на true, али не зауставља већ покренуту методу main(). Код унутар main() мора самостално да проверава isCancelled и да се заврши по потреби. Ово је архитектонска одлука Apple-а — која омогућава програмеру да правилно ослободи ресурсе при отказивању.
KVO наблюдение својстава isFinished и isExecuting омогућава реакцију на завршетак операција без експлицитног callback-а. OperationQueue автоматично уклања завршене операције из опашкаа, али one остају у меморији док постоје јаке референце. KVO је основа за интеграцију OperationQueue-а са реактивним framework-има попут RxSwift или Combine.
Претплата на isCancelled путем KVO-а омогућава ажурирање UI-ја при отказивању операције — на пример, приказ placeholder-а уместо отказаног учитавања. Својство isCancelled је KVO-компатибилно, што га чини погодним за реактивне pipeline-ове.
Немојте креирати операције у великом броју — свака Operation је засебан објекат у меморији. Ако је задатак кратак и не захтева зависности, користите DispatchQueue директно. OperationQueue је оправдана само за сложене сценарије са експлицитним зависностима, отмянам и праћењем напретка.
Проверавајте isCancelled пре скупих операција унутар методе main(). У случају преузимања датотека или обраде слика, провера након сваког значајног корака обезбеђује брз одговор на отмяна. Користите if isCancelled { return } на почетку main() и након сваке велике операције.
Правилно управлявајте completionBlock-ом. Својство completionBlock операције се позива након завршетка main(), чак и ако је операција отказана. Проверавајте isCancelled унутар completionBlock-а да не бисте ажурирали UI погрешним подацима. OperationQueue.main — нитно безбедан опашка за UI операције, аналоган DispatchQueue.main-у.
Избегавајте цикличне зависности — one доводе до тога да се ниједна од операција у циклусу никада не покрене. OperationQueue не детектује циклусе автоматично: ако A зависи од B, а B зависи од A, обе заувек остају у стању ready. Планирајте граф зависности унапопашка.
Често постављана питања
OperationQueue је изградена изнад GCD-а и додаје зависности, приоритети, KVO и отмяна операција. DispatchQueue је лакши алат за једноставне async задатке без ових могућности.
Поставите свойство maxConcurrentOperationCount на 1. Ово претвара OperationQueue у sequential опашка уз задржавање свих попашканости — зависности, приоритета и отказивања.
Метода cancel() поставља заставицу isCancelled, али не зауставља методу main() која се извршава. Код операције мора сам да проверава isCancelled и да се заврши. Отказивање ради само за pending и ready операције.
Операцију треба наследити када је потребно управлявање стањем, асинхроност или поновно коришћење логике. BlockOperation је погодан за једноставне једнократне задатке без наслеђивања.
Не, осим ако је метода waitUntilFinished позвана са true параметром на главној нити. Операције се подразумевано извршавају на позадинским нитима, а резултат се враћа путем OperationQueue.main.
Резиме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също