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. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође