OperationQueue ist eine hochrangige Aufgabenwarteschlange in iOS und macOS, die auf Grand Central Dispatch aufbaut. Laut Apple Developer Documentation, 2026 verwaltet OperationQueue Instanzen von Operation — Objekte, die eine Arbeitseinheit kapseln. Im Gegensatz zu DispatchQueue unterstützt OperationQueue Abhängigkeiten zwischen Operationen, Prioritäten, KVO-Beobachtung und den Abbruch laufender Aufgaben. OperationQueue verwaltet automatisch einen Thread-Pool und verteilt Operationen auf die verfügbaren Systemressourcen.
Wichtige Punkte
OperationQueue ist eine Klasse aus dem Foundation-Framework, die die Ausführung von Operation-Objekten verwaltet. Im Gegensatz zu DispatchQueue muss bei OperationQueue nicht explizit der serielle oder Concurrent-Modus angegeben werden — die Anzahl der gleichzeitig ausgeführten Operationen wird durch die Eigenschaft maxConcurrentOperationCount gesteuert. Der Wert 1 macht die Warteschlange sequenziell, jeder andere Wert macht sie concurrent.
Operation ist eine abstrakte Klasse, die eine Arbeitseinheit darstellt. Jede Operation hat einen Zustand: ready, executing, finished oder cancelled. Die Zustände sind KVO-kompatibel (Key-Value Observing), sodass auf Änderungen reagiert werden kann — zum Beispiel die Aktualisierung der Benutzeroberfläche beim Abschluss einer Operation. Operation verwaltet automatisch die Flags isExecuting und isFinished.
Laut Apple (2026) verwendet OperationQueue intern GCD, fügt aber Funktionalität hinzu, die in DispatchQueue nicht verfügbar ist: Abhängigkeiten, Prioritäten und Abbruch von Operationen. Wenn die App in den Hintergrund wechselt, setzt OperationQueue die Ausführung aus und nimmt sie bei der Rückkehr wieder auf. OperationQueue berücksichtigt automatisch die Anzahl der CPU-Kerne und wählt die optimale Anzahl von Threads.
Jede Operation durchläuft vier Zustände: pending (ausstehend), ready (bereit), executing (ausführend) und finished (abgeschlossen). Der Zustand cancelled kann in jeder Phase vor dem Abschluss eintreten. Zustandsübergänge werden über KVO verfolgt — dies ist die Grundlage für reaktive UI-Updates. OperationQueue entfernt abgeschlossene Operationen automatisch aus der Warteschlange und benachrichtigt abhängige Operationen, dass ihre Voraussetzung erfüllt ist, und startet deren Ausführung.
Operation ist eine abstrakte Klasse, die das Überschreiben der Methode main() oder start() erfordert. Der Aufgaben-Code wird in die Methode main() eingefügt, und die Zustände isExecuting und isFinished werden automatisch verwaltet. Für asynchrone Operationen muss start() überschrieben werden und die Zustandsflags manuell verwaltet werden.
BlockOperation ist eine konkrete Implementierung von Operation, die einen oder mehrere Codeblöcke ausführt. BlockOperation wird concurrent, wenn mehrere Blöcke über addExecutionBlock() hinzugefügt werden. Die Operation wird erst abgeschlossen, nachdem alle hinzugefügten Blöcke ausgeführt wurden. BlockOperation ist eine praktische Alternative für einfache Aufgaben ohne Vererbung.
| Merkmal | Operation | BlockOperation |
|---|---|---|
| Klassentyp | Abstrakt | Konkret |
| Vererbung | Erforderlich | Nicht erforderlich |
| Asynchronität | Manuelle KVO-Verwaltung | Automatisch |
| Codeblöcke | Einer in main() | Einer oder mehrere |
| Verwendung | Komplexe Aufgaben mit Zustand | Einfache einmalige Aufgaben |
| Geeignet für | Abhängigkeiten, Abbruch, Fortschritt | Schnelle Blöcke, Abschluss |
| Speicher | Höher durch KVO und Zustand | Minimal, leichtgewichtig |
Um eine benutzerdefinierte Operation zu erstellen, leiten Sie von Operation ab und überschreiben main(). Überprüfen Sie darin das Flag isCancelled vor teuren Operationen, um einen schnellen Abbruch zu gewährleisten. Dies ist kritisch für das Herunterladen großer Dateien oder die Stapelverarbeitung von Daten. Die Wahl zwischen Operation und BlockOperation hängt von der Aufgabenkomplexität ab: für einfache einmalige Aktionen ist BlockOperation ausreichend; für wiederverwendbare Logik mit Zustand leiten Sie von Operation ab.
Abhängigkeiten sind der Hauptvorteil von OperationQueue gegenüber DispatchQueue. Die Methode addDependency(_:) legt fest, dass Operation B erst nach Abschluss von Operation A ausgeführt wird. Abhängigkeiten bilden einen gerichteten azyklischen Graphen (DAG): wird eine zyklische Abhängigkeit hinzugefügt, ignoriert die Warteschlange sie und die Operationen werden nicht gestartet.
Priorität einer Operation wird über die Eigenschaft queuePriority mit Werten festgelegt: .veryLow, .low, .normal, .high, .veryHigh. Die Priorität beeinflusst die Startreihenfolge unter bereiten Operationen, überschreibt jedoch keine Abhängigkeiten. OperationQueue löst zuerst Abhängigkeiten auf und wendet dann die Priorität unter den verfügbaren Operationen an.
Ein typisches Szenario ist das Laden von Profildaten: zuerst den Benutzer laden, dann basierend auf seiner ID Freunde und Beiträge laden. Das Setzen einer Abhängigkeit zwischen Benutzer laden und Freunde laden garantiert die korrekte Reihenfolge ohne verschachtelte Completion-Handler.
Die Eigenschaft maxConcurrentOperationCount begrenzt die Anzahl der gleichzeitig ausgeführten Operationen. Der Wert 1 erstellt eine sequenzielle Warteschlange, der Standardwert (NSOperationQueueDefaultMaxConcurrentOperationCount) ist systemoptimal und hängt von der aktuellen Geräteauslastung ab. Die richtige Konfiguration dieses Parameters verhindert übermäßigen Ressourcenverbrauch: zum Laden von Bildern sind 4–6 gleichzeitige Operationen ausreichend; für CPU-intensive Aufgaben verwenden Sie die Anzahl der Prozessorkerne.
Die Wahl zwischen OperationQueue und DispatchQueue hängt von der Aufgabenkomplexität ab. DispatchQueue ist ein leichtes Werkzeug für einfache asynchrone Aufrufe. OperationQueue ist eine schwerere Lösung für komplexe Szenarien mit vielen miteinander verbundenen Aufgaben. Apple empfiehlt, mit DispatchQueue zu beginnen und nur dann zu OperationQueue zu wechseln, wenn Abhängigkeiten oder Abbruch benötigt werden. Für die meisten iOS-Projekte bietet eine Kombination beider Werkzeuge eine optimale Balance zwischen Leistung und Flexibilität.
Laut Ray Wenderlich (2025) wird OperationQueue in großen iOS-Projekten zum Laden von Inhalten mit Fortschritt und Abbruch verwendet, während DispatchQueue für alle anderen asynchronen Operationen verwendet wird. Das Verhältnis beträgt etwa 20 zu 80 zugunsten von DispatchQueue.
Betrachten wir drei Beispiele: eine einfache BlockOperation, eine benutzerdefinierte Operation mit Abhängigkeiten und eine abbrechbare Operation zum Laden von Daten.
Der einfachste Fall — einen Block auf OperationQueue ausführen und das Ergebnis über completionBlock verarbeiten. Jede Operation hat eine eingebaute completionBlock-Eigenschaft, die nach Beendigung von main() aufgerufen wird.
let queue = OperationQueue()
let operation = BlockOperation()
operation.addExecutionBlock {
let data = NetworkService.fetchData()
OperationQueue.main.addOperation {
self.updateUI(data)
}
}
queue.addOperation(operation)
Die Abhängigkeit stellt sicher, dass parseOperation erst startet, nachdem downloadOperation abgeschlossen ist. Dies macht verschachtelte Callbacks überflüssig.
let download = BlockOperation { self.downloadJSON() }
let parse = BlockOperation { self.parseJSON() }
parse.addDependency(download)
let queue = OperationQueue()
queue.addOperations([download, parse], waitUntilFinished: false)
Überschreiben Sie main() mit regelmäßigen isCancelled-Überprüfungen. Dies ermöglicht der Operation, beim Abbruch sofort anzuhalten, ohne auf den Abschluss einer teuren Operation zu warten.
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) }
}
}
Der Abbruch einer Operation setzt das Flag isCancelled auf true, stoppt aber nicht die bereits ausgeführte Methode main(). Der Code innerhalb von main() muss selbst isCancelled überprüfen und bei Bedarf beenden. Dies ist eine architektonische Entscheidung von Apple — die es dem Entwickler ermöglicht, Ressourcen beim Abbruch ordnungsgemäß freizugeben.
Die KVO-Beobachtung der Eigenschaften isFinished und isExecuting ermöglicht es, auf den Abschluss von Operationen ohne explizite Callbacks zu reagieren. OperationQueue entfernt abgeschlossene Operationen automatisch aus der Warteschlange, aber sie bleiben im Speicher, solange starke Referenzen auf sie bestehen. KVO ist die Grundlage für die Integration von OperationQueue mit reaktiven Frameworks wie RxSwift oder Combine.
Das Abonnieren von isCancelled über KVO ermöglicht die Aktualisierung der Benutzeroberfläche beim Abbruch einer Operation — zum Beispiel das Anzeigen eines Platzhalters anstelle eines abgebrochenen Downloads. Die Eigenschaft isCancelled ist KVO-kompatibel, was sie für reaktive Pipelines praktisch macht.
Erstellen Sie keine großen Mengen von Operationen — jede Operation ist ein separates Objekt im Speicher. Wenn eine Aufgabe kurz ist und keine Abhängigkeiten erfordert, verwenden Sie direkt DispatchQueue. OperationQueue ist für komplexe Szenarien mit expliziten Abhängigkeiten, Abbruch und Fortschrittsüberwachung gerechtfertigt.
Überprüfen Sie isCancelled vor teuren Operationen innerhalb der main()-Methode. Bei Dateidownloads oder Bildverarbeitung gewährleistet die Überprüfung nach jedem bedeutenden Schritt eine schnelle Reaktion auf Abbruch. Verwenden Sie if isCancelled { return } am Anfang von main() und nach jeder größeren Operation.
Verwalten Sie completionBlock richtig. Die completionBlock-Eigenschaft einer Operation wird nach Abschluss von main() aufgerufen, auch wenn die Operation abgebrochen wurde. Überprüfen Sie isCancelled innerhalb von completionBlock, um die Benutzeroberfläche nicht mit fehlerhaften Daten zu aktualisieren. OperationQueue.main ist eine threadsichere Warteschlange für UI-Operationen, ähnlich wie DispatchQueue.main.
Vermeiden Sie zyklische Abhängigkeiten — sie führen dazu, dass keine der Operationen im Zyklus jemals startet. OperationQueue erkennt Zyklen nicht automatisch: wenn A von B abhängt und B von A, bleiben beide für immer im Zustand ready. Planen Sie den Abhängigkeitsgraphen im Voraus.
Häufig gestellte Fragen
OperationQueue ist auf GCD aufgebaut und fügt Abhängigkeiten, Prioritäten, KVO und Operationsabbruch hinzu. DispatchQueue ist ein leichteres Werkzeug für einfache asynchrone Aufgaben ohne diese Funktionen.
Setzen Sie die Eigenschaft maxConcurrentOperationCount auf 1. Dies verwandelt OperationQueue in eine sequenzielle Warteschlange unter Beibehaltung aller Vorteile — Abhängigkeiten, Prioritäten und Abbruch.
Die Methode cancel() setzt das Flag isCancelled, stoppt aber nicht die ausgeführte main()-Methode. Der Operationscode muss selbst isCancelled überprüfen und beenden. Der Abbruch funktioniert nur für ausstehende und bereite Operationen.
Sie sollten von Operation ableiten, wenn Sie Zustandsverwaltung, Asynchronität oder Logikwiederverwendung benötigen. BlockOperation eignet sich für einfache einmalige Aufgaben ohne Vererbung.
Nein, es sei denn, Sie rufen waitUntilFinished mit dem Parameter true im Hauptthread auf. Operationen werden standardmäßig auf Hintergrundthreads ausgeführt, und Ergebnisse werden über OperationQueue.main zurückgegeben.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch