Το OperationQueue είναι μια ουρά εργασιών υψηλού επιπέδου σε iOS και macOS, χτισμένη πάνω από το Grand Central Dispatch. Σύμφωνα με την Apple Developer Documentation, 2026, το OperationQueue διαχειρίζεται στιγμιότυπα Operation — αντικείμενα που ενσωματώνουν μια μονάδα εργασίας. Σε αντίθεση με το DispatchQueue, το OperationQueue υποστηρίζει εξαρτήσεις μεταξύ λειτουργιών, προτεραιότητες, παρατήρηση KVO και ακύρωση εκτελούμενων εργασιών. Το OperationQueue διαχειρίζεται αυτόματα τη δεξαμενή νημάτων, κατανέμοντας τις λειτουργίες στους διαθέσιμους πόρους του συστήματος.
Σημαντικά
OperationQueue είναι μια κλάση από το πλαίσιο 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. Οι εξαρτήσεις σχηματίζουν ένα κατευθυνόμενο ακυκλικό γράφημα (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 αφαιρεί αυτόματα τις ολοκληρωμένες λειτουργίες από την ουρά, αλλά αυτές παραμένουν στη μνήμη όσο υπάρχουν ισχυρές αναφορές σε αυτές. Το KVO αποτελεί τη βάση για ενσωμάτωση του OperationQueue με αντιδραστικά πλαίσια όπως 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.
Αποφύγετε κυκλικές εξαρτήσεις — οδηγούν στο να μην εκτελείται ποτέ καμία από τις λειτουργίες στον κύκλο. Το OperationQueue δεν ανιχνεύει αυτόματα κύκλους: εάν το A εξαρτάται από το B και το B εξαρτάται από το A, και οι δύο θα παραμείνουν για πάντα σε κατάσταση ready. Σχεδιάστε το γράφημα εξαρτήσεων εκ των προτέρων.
Συχνές ερωτήσεις
Το OperationQueue είναι χτισμένο πάνω από το GCD και προσθέτει εξαρτήσεις, προτεραιότητες, KVO και ακύρωση λειτουργιών. Το DispatchQueue είναι ένα πιο ελαφρύ εργαλείο για απλές async εργασίες χωρίς αυτές τις δυνατότητες.
Ορίστε την ιδιότητα maxConcurrentOperationCount σε 1. Αυτό μετατρέπει το OperationQueue σε sequential ουρά διατηρώντας όλα τα πλεονεκτήματα — εξαρτήσεις, προτεραιότητες και ακύρωση.
Η μέθοδος cancel() θέτει τη σημαία isCancelled, αλλά δεν σταματά την εκτελούμενη μέθοδο main(). Ο κώδικας της λειτουργίας πρέπει να ελέγχει το isCancelled και να τερματίζει. Η ακύρωση λειτουργεί μόνο για pending και ready λειτουργίες.
Αξίζει να κληρονομήσετε από την Operation όταν απαιτείται διαχείριση κατάστασης, ασυγχρονία ή επαναχρησιμοποίηση λογικής. Το BlockOperation είναι κατάλληλο για απλές εφάπαξ εργασίες χωρίς κληρονομικότητα.
Όχι, εκτός εάν κληθεί η μέθοδος waitUntilFinished με παράμετρο true στο κύριο νήμα. Οι λειτουργίες εκτελούνται προεπιλεγμένα σε νήματα παρασκηνίου, ενώ το αποτέλεσμα επιστρέφεται μέσω του OperationQueue.main.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης