Az OperationQueue egy magas szintű feladatsor iOS-ben és macOS-ben, amely a Grand Central Dispatch-re épül. A Apple Developer Documentation, 2026 szerint az OperationQueue Operation példányokat kezel — olyan objektumokat, amelyek egy munkavégzést egységet zárnak be. A DispatchQueue-tól eltérően az OperationQueue támogatja a műveletek közötti függőségeket, prioritásokat, KVO-megfigyelést és az elindított feladatok megszakítását. Az OperationQueue automatikusan kezeli a szálpoolt, és a műveleteket a rendszer rendelkezésre álló erőforrásai szerint osztja el.
Főbb pontok
OperationQueue egy osztály a Foundation keretrendszerből, amely az Operation objektumok végrehajtását kezeli. A DispatchQueue-tól eltérően az OperationQueue nem igényli a serial vagy concurrent mód explicit megadását — az egyidejűleg végrehajtott műveletek számát a maxConcurrentOperationCount tulajdonság szabályozza. Az 1 érték sequential-lé alakítja a sort, bármely más érték concurrent-té.
Operation egy absztrakt osztály, amely egy munkaegységet reprezentál. Minden művelet rendelkezik állapottal: ready, executing, finished vagy cancelled. Az állapotok kompatibilisek a KVO-val (Key-Value Observing), ami lehetővé teszi a változásokra való reagálást — például a UI frissítését egy művelet befejezésekor. Az Operation automatikusan kezeli az isExecuting és isFinished jelzőket.
Az Apple (2026) szerint az OperationQueue belsőleg GCD-t használ, de olyan funkcionalitást ad hozzá, ami nem érhető el a DispatchQueue-ban: függőségek, prioritások és a műveletek megszakítása. Ha az alkalmazás háttérmódba lép, az OperationQueue felfüggeszti a végrehajtást, és visszatéréskor folytatja. Az OperationQueue automatikusan figyelembe veszi a processzormagok számát és kiválasztja az optimális szálszámot.
Minden művelet négy állapoton megy keresztül: pending (várakozás), ready (indításra kész), executing (végrehajtás alatt) és finished (befejeződött). A cancelled állapot a befejeződés előtt bármely szakaszban bekövetkezhet. Az állapotok közötti átmeneteket a KVO követi nyomon — ez a reaktív UI-frissítések alapja. Az OperationQueue automatikusan eltávolítja a befejezett műveleteket a sorból, és értesíti a függő műveleteket, hogy az előfeltételük teljesült, elindítva azok végrehajtását.
Operation egy absztrakt osztály, amely a main() vagy start() metódus felülírását igényli. A main() metódusban helyezkedik el a feladat kódja, és az isExecuting és isFinished állapot automatikusan kerül kezelésre. Aszinkron műveletek esetén a start() felülírása és az állapotjelzők kézi kezelése szükséges.
BlockOperation az Operation konkrét megvalósítása, amely egy vagy több kódblokkot hajt végre. A BlockOperation concurrent-té válik, ha több blokkot adunk hozzá a addExecutionBlock() segítségével. A művelet csak az összes hozzáadott blokk végrehajtása után fejeződik be. A BlockOperation kényelmes alternatíva egyszerű, öröklést nem igénylő feladatokhoz.
| Jellemző | Operation | BlockOperation |
|---|---|---|
| Osztály típusa | Absztrakt | Konkrét |
| Öröklés | Szükséges | Nem szükséges |
| Aszinkronitás | Kézi KVO-kezelés | Automatikus |
| Kódblokkok | Egy a main()-ben | Egy vagy több |
| Alkalmazás | Állapottal rendelkező összetett feladatok | Egyszerű egyszeri feladatok |
| Alkalmas | Függőségek, megszakítás, előrehaladás | Gyors blokkok, completion |
| Memória | Magasabb a KVO és állapot miatt | Minimális, könnyű |
Egyéni művelet létrehozásához örököljön az Operation-ből és írja felül a main()-t. Belül ellenőrizze az isCancelled jelzőt a költséges műveletek előtt a gyors megszakítás biztosítása érdekében. Ez kritikus fontosságú nagy fájlok letöltése vagy kötegelt adatfeldolgozás esetén. Választás az Operation és a BlockOperation között a feladat összetettségétől függ: egyszerű egyszeri műveletekhez a BlockOperation elegendő, állapottal rendelkező újrafelhasználható logikához — öröklés az Operation-ből.
Függőségek az OperationQueue legfőbb előnye a DispatchQueue-val szemben. A addDependency(_:) metódus meghatározza, hogy a B művelet csak az A művelet befejeződése után hajtódik végre. A függőségek directed acyclic graph-ot (DAG) alkotnak: ciklikus függőség hozzáadásakor a sor figyelmen kívül hagyja azt, és a műveletek nem indulnak el.
A művelet prioritása a queuePriority tulajdonsággal állítható be: .veryLow, .low, .normal, .high, .veryHigh. A prioritás befolyásolja az indítási sorrendet a ready műveletek között, de nem váltja fel a függőségeket. Az OperationQueue először a függőségeket veszi figyelembe, majd a prioritást az elérhető műveletek között.
Tipikus forgatókönyv — profiladatok betöltése: először a felhasználót töltjük be, majd az id-ja alapján a barátokat és bejegyzéseket. A felhasználó betöltése és a barátok betöltése közötti függőség beállítása garantálja a helyes sorrendet egymásba ágyazott completion handler-ek nélkül.
A maxConcurrentOperationCount tulajdonság korlátozza az egyidejűleg végrehajtott műveletek számát. Az 1 érték sequential sort hoz létre, az alapértelmezett érték (NSOperationQueueDefaultMaxConcurrentOperationCount) — rendszeroptális, az eszköz aktuális terhelésétől függően. A paraméter helyes beállítása megakadályozza a túlzott erőforrás-fogyasztást: képek betöltéséhez 4-6 concurrent művelet elegendő, CPU-intenzív feladatokhoz — a processzormagok száma.
A választás az OperationQueue és a DispatchQueue között a feladat összetettségétől függ. A DispatchQueue egy könnyű eszköz egyszerű async hívásokhoz. Az OperationQueue egy nehezebb megoldás összetett forgatókönyvekhez, több egymással összefüggő feladattal. Az Apple azt ajánlja, hogy kezdje a DispatchQueue-val, és csak akkor váltson OperationQueue-ra, ha függőségekre vagy megszakításra van szükség. A legtöbb iOS-projektben a két eszköz kombinációja optimális egyensúyt biztosít a teljesítmény és a rugalmasság között.
Ray Wenderlich (2025) szerint, nagy iOS-projektekben az OperationQueue-t a tartalom előrehaladással és megszakítással történő betöltésére használják, a DispatchQueue-t pedig az összes többi async művelethez. Az arány körülbelül 20 a 80-hoz a DispatchQueue javára.
Három példát tekintünk át: egy egyszerű BlockOperation-t, egy egyéni Operation-t függőségekkel és egy megszakítható műveletet adatok betöltéséhez.
A legegyszerűbb eset — hajtson végre egy blokkot az OperationQueue-n és dolgozza fel az eredményt a completionBlock segítségével. Minden Operation rendelkezik egy beépített completionBlock tulajdonsággal, amely a main() befejeződése után hívódik meg.
let queue = OperationQueue()
let operation = BlockOperation()
operation.addExecutionBlock {
let data = NetworkService.fetchData()
OperationQueue.main.addOperation {
self.updateUI(data)
}
}
queue.addOperation(operation)
Függőség garantálja, hogy a parseOperation csak a downloadOperation befejeződése után indul el. Ez kiküszöböli az egymásba ágyazott callback-ek szükségességét.
let download = BlockOperation { self.downloadJSON() }
let parse = BlockOperation { self.parseJSON() }
parse.addDependency(download)
let queue = OperationQueue()
queue.addOperations([download, parse], waitUntilFinished: false)
Írja felül a main()-t az isCancelled időszakos ellenőrzésével. Ez lehetővé teszi a művelet azonnali leállítását megszakításkor, anélkül, hogy megvárna a költséges művelet befejeződését.
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) }
}
}
A művelet megszakítása az isCancelled jelzőt true értékre állítja, de nem állítja le a már elindított main() metódust. A main()-en belüli kódnak önállóan kell ellenőriznie az isCancelled-t és szükség esetén befejeződnie. Ez az Apple architektúrális döntése — amely lehetővé teszi a fejlesztő számára, hogy megszakításkor helyesen szabadítsa fel az erőforrásokat.
KVO-megfigyelés az isFinished és isExecuting tulajdonságokon lehetővé teszi a műveletek befejeződésére való reagálást explicit callback nélkül. Az OperationQueue automatikusan eltávolítja a befejezett műveleteket a sorból, de azok a memóriában maradnak, amíg erős hivatkozások léteznek rájuk. KVO az OperationQueue reaktív keretrendszerekkel (RxSwift vagy Combine) való integrációjának alapja.
Az isCancelled-re való feliratkozás KVO-n keresztül lehetővé teszi a UI frissítését egy művelet megszakításakor — például egy placeholder megjelenítését a megszakított letöltés helyett. Az isCancelled tulajdonság KVO-kompatibilis, ami kényelmessé teszi a reaktív pipeline-ok számára.
Ne hozzon létre nagy számú műveletet — minden Operation külön objektum a memóriában. Ha a feladat rövid és nem igényel függőségeket, használja közvetlenül a DispatchQueue-t. Az OperationQueue csak összetett forgatókönyvek esetén indokolt, explicit függőségekkel, megszakítással és előrehaladás követésével.
Ellenőrizze az isCancelled-t a költséges műveletek előtt a main() metóduson belül. Fájlok letöltése vagy képek feldolgozása esetén az ellenőrzés minden jelentős lépés után gyors választ biztosít a megszakításra. Használja az if isCancelled { return } kódot a main() elején és minden nagy művelet után.
Kezelje helyesen a completionBlock-ot. A művelet completionBlock tulajdonsága a main() befejeződése után hívódik meg, akkor is, ha a művelet meg lett szakítva. Ellenőrizze az isCancelled-t a completionBlock-on belül, hogy ne frissítse a UI-t téves adatokkal. OperationQueue.main — egy szálbiztos sor UI-műveletekhez, hasonlóan a DispatchQueue.main-hoz.
Kerülje a ciklikus függőségeket — azok ahhoz vezetnek, hogy a ciklusban lévő műveletek egyike sem indul el soha. Az OperationQueue nem érzékeli automatikusan a ciklusokat: ha A függ B-től, és B függ A-tól, mindkettő örökre ready állapotban marad. Tervezze meg a függőségi gráfot előre.
Gyakran ismételt kérdések
Az OperationQueue a GCD-re épül és függőségeket, prioritásokat, KVO-t és a műveletek megszakítását adja hozzá. A DispatchQueue egy könnyebb eszköz egyszerű async feladatokhoz, ezen képességek nélkül.
Állítsa a maxConcurrentOperationCount tulajdonságot 1-re. Ez az OperationQueue-t sequential sorrá alakítja, miközben megtartja az összes előnyt — függőségeket, prioritásokat és megszakítást.
A cancel() metódus beállítja az isCancelled jelzőt, de nem állítja le a végrehajtódó main() metódust. A művelet kódjának magának kell ellenőriznie az isCancelled-t és befejeződnie. A megszakítás csak a pending és ready műveleteknél működik.
A műveletet örökölni kell, amikor állapotkezelés, aszinkronitás vagy a logika újrafelhasználása szükséges. A BlockOperation öröklést nem igénylő egyszerű egyszeri feladatokhoz alkalmas.
Nem, hacsak a waitUntilFinished metódust nem hívják meg true paraméterrel a főszálon. A műveletek alapértelmezésben háttérszálakon futnak, és az eredmény az OperationQueue.main-en keresztül kerül visszaadásra.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is