Do-Catch: τι είναι, κατασκευή και διαχείριση σφαλμάτων στη Swift

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-05-26 Χρόνος ανάγνωσης: 8 λεπ

Do-Catch — κατασκευή της γλώσσας Swift για διαχείριση σφαλμάτων που πιάνει εξαιρέσεις που εκτοξεύονται μέσω throw και εκτελεί το αντίστοιχο μπλοκ κώδικα. Σε αντίθεση με το παραδοσιακό try-catch σε άλλες γλώσσες, η Swift απαιτεί ρητή σήμανση των συναρτήσεων που μπορούν να εκτοξεύσουν σφάλμα με τον τροποποιητή throws. Σύμφωνα με το Swift.org, 2026, το Do-Catch είναι ο κύριος μηχανισμός διαχείρισης σφαλμάτων στη Swift, που εξασφαλίζει ασφάλεια σε επίπεδο τύπων.

Κύρια σημεία

  • Do-Catch — κατασκευή Swift που πιάνει σφάλματα από μπλοκ με try και throw.
  • throws — δείκτης συνάρτησης που σηματοδοτεί ότι μπορεί να εκτοξεύσει σφάλμα.
  • try — λέξη-κλειδί για κλήση throwing-συνάρτησης μέσα σε μπλοκ do.
  • catch — μπλοκ διαχείρισης σφάλματος με δυνατότητα αντιστοίχισης κατά τύπο.
  • try? και try! — εναλλακτικές μορφές που μετατρέπουν το σφάλμα σε nil ή προκαλούν crash.

Τι είναι το Do-Catch;

Do-Catch — είναι μια κατασκευή στη Swift που αποτελείται από ένα μπλοκ do, μέσα στο οποίο εκτελείται κώδικας ικανός να εκτοξεύσει σφάλμα, και ένα ή περισσότερα μπλοκ catch που διαχειρίζονται αυτό το σφάλμα. Το μπλοκ do περιέχει κλήσεις throwing-συναρτήσεων σημειωμένες με try, και τα μπλοκ catch αντιστοιχίζουν το σφάλμα κατά τύπο.

Η Swift υλοποιεί το μοντέλο δομημένης διαχείρισης σφαλμάτων, διαφορετικό από τις εξαιρέσεις στην Objective-C. Εδώ το σφάλμα δεν είναι exception με ξετύλιγμα στοίβας, αλλά μια τιμή που αντιστοιχεί στο πρωτόκολλο Error. Η εκτόξευση σφάλματος μέσω throw μεταφέρει τον έλεγχο στο πλησιέστερο μπλοκ catch χωρίς την επιβάρυνση του ξετυλίγματος στοίβας.

Το βασικό χαρακτηριστικό της Swift — η ρητότητα διαχείρισης. Ο μεταγλωττιστής δεν επιτρέπει την κλήση throwing-συνάρτησης χωρίς try, do-catch ή εναλλακτικό μηχανισμό (try?, try!). Αυτό εξαλείφει καταστάσεις όπου ένα σφάλμα παραμένει απαρατήρητο.

Μοντέλο σφαλμάτων στη Swift: πρωτόκολλο Error και throwing συναρτήσεις

Η βάση της διαχείρισης σφαλμάτων στη Swift είναι το πρωτόκολλο Error. Οποιοσδήποτε τύπος που αντιστοιχεί σε αυτό το πρωτόκολλο μπορεί να εκτοξευθεί μέσω throw. Συνήθως τα σφάλματα ορίζονται ως enum με επιβεβαίωση Error.

Πρωτόκολλο Error

Error — ένα κενό πρωτόκολλο (δείκτης). Δεν απαιτεί υλοποίηση μεθόδων, μόνο επιβεβαίωση συμμόρφωσης. Ο μεταγλωττιστής Swift χρησιμοποιεί το Error για στατικό έλεγχο: μια συνάρτηση με throws μπορεί να εκτοξεύσει μόνο τιμή που αντιστοιχεί στο Error.

Throwing συναρτήσεις

Μια συνάρτηση σημειωμένη με throws πρέπει να καλείται με try. Αν μέσα σε μια τέτοια συνάρτηση συμβεί throw, ο έλεγχος μεταφέρεται στο καλούν do-catch. Αν το σφάλμα δεν διαχειριστεί πουθενά στην αλυσίδα κλήσεων, προωθείται σε ανώτερο επίπεδο.

swift
enum FileError: Error {
    case notFound
    case permissionDenied
    case corrupted(String)
}

func readFile(path: String) throws -> String {
    guard FileManager.default.fileExists(atPath: path) else {
        throw FileError.notFound
    }
    return try String(contentsOfFile: path)
}

Διάδοση σφάλματος rethrows

rethrows — τροποποιητής για συναρτήσεις που δέχονται throwing-closure ως παράμετρο. Αν το μεταβιβασμένο closure δεν εκτοξεύει σφάλμα, η rethrows συνάρτηση μπορεί να κληθεί χωρίς try. Αυτό επιτρέπει τη σύνταξη γενικών συναρτήσεων ανώτερης τάξης συμβατών με throwing και non-throwing closures.

Σύνταξη Do-Catch: πολλαπλά μπλοκ catch

Η Swift υποστηρίζει πολλαπλά μπλοκ catch με αντιστοίχιση κατά τύπο σφάλματος. Αυτό μοιάζει με το when στην Kotlin ή switch κατά τύπο: το πρώτο ταιριαστό catch εκτελείται, τα υπόλοιπα παραλείπονται.

Αντιστοίχιση κατά τύπο

Κάθε μπλοκ catch μπορεί να περιέχει ένα μοτίβο αντιστοίχισης με συγκεκριμένο τύπο σφάλματος. Η Swift ελέγχει τα μπλοκ με τη σειρά, επομένως πιο συγκεκριμένοι τύποι πρέπει να βρίσκονται πριν από γενικούς. Αν κανένα μοτίβο δεν ταιριάζει, εκτελείται το μπλοκ catch χωρίς μοτίβο.

Διαχείριση πολλαπλών τύπων

Ασφάλεια τύπων Το Do-Catch επιτρέπει τη διαχείριση κάθε σφάλματος ξεχωριστά ή το συνδυασμό πολλαπλών τύπων σε ένα μπλοκ μέσω κόμματος στο pattern-matching. Αυτό εξαλείφει τις ογκώδεις αλυσίδες if-else που χαρακτηρίζουν την Objective-C, όπου η ανάλυση σφάλματος γινόταν μέσω κωδικού επιστροφής ή NSError με έλεγχο domain και code.

Η Swift υποστηρίζει επίσης catch where — αντιστοίχιση με πρόσθετη συνθήκη. Για παράδειγμα, μπορεί κανείς να φιλτράρει σφάλματα κατά συγκεκριμένο κωδικό ή κείμενο: catch URLError where error.code == .notConnectedToInternet. Αυτό μειώνει τον αριθμό των μπλοκ catch διατηρώντας την ακρίβεια διαχείρισης.

Για τον εντοπισμό σφαλμάτων σε throwing συναρτήσεις, η Swift παρέχει τη διαφορά μεταξύ σφαλμάτων και εξαιρέσεων. Το σφάλμα Swift — είναι μια επιστρεφόμενη τιμή που δεν απαιτεί ξετύλιγμα στοίβας. Οι εξαιρέσεις Objective-C (@try/@catch) λειτουργούν σε επίπεδο runtime και χρησιμοποιούνται μόνο για μοιραίες βλάβες. Το Do-Catch διαχειρίζεται ακριβώς σφάλματα, όχι εξαιρέσεις, που το καθιστά προβλέψιμο και αποδοτικό.

Κατά την ανάπτυξη βιβλιοθηκών και SDK, είναι σημαντικό να θυμόμαστε ότι οι throwing συναρτήσεις αποτελούν μέρος της δημόσιας σύμβασης. Ο τύπος σφάλματος δεν προσδιορίζεται στην υπογραφή, επομένως τεκμηριώστε ποια σφάλματα μπορεί να εκτοξεύσει η συνάρτηση σε ένα σχόλιο ή μέσω ενός enum τύπου Result. Αυτό βοηθά τους χρήστες API να γράφουν σωστά μπλοκ catch χωρίς να χρειάζεται να κοιτάζουν στην υλοποίηση.

Στο πλαίσιο του ασύγχρονου προγραμματισμού, το Do-Catch με async/await λύνει το πρόβλημα callback hell. Παλαιότερα στη Swift, η διαχείριση σφαλμάτων σε ασύγχρονο κώδικα απαιτούσε ένθετα closures με έλεγχο Error? στο completion handler. Με async/await και Do-Catch, ο ασύγχρονος throwing κώδικας μοιάζει με σύγχρονο, που απλοποιεί την ανάγνωση και συντήρηση σύνθετων αλυσίδων αιτημάτων με διαχείριση σφαλμάτων σε κάθε βήμα.

swift
do {
    let content = try readFile(path: "/data/config.json")
    process(content)
} catch FileError.notFound {
    createDefaultConfig()
} catch FileError.permissionDenied {
    requestAccess()
} catch FileError.corrupted(let detail) {
    logCorruption(detail)
} catch {
    print("Άγνωστο σφάλμα: \(error)")
}

Παραλλαγές try: try, try?, try! και πότε να χρησιμοποιούνται

Η Swift προσφέρει τρεις παραλλαγές κλήσης throwing συναρτήσεων: try, try? και try!. Κάθε παραλλαγή λύνει ένα συγκεκριμένο πρόβλημα και έχει τους περιορισμούς της.

try — τυπική κλήση

try χρησιμοποιείται μέσα σε μπλοκ do, και το σφάλμα διαχειρίζεται στο catch. Αυτός είναι ο κύριος τρόπος κλήσης throwing συναρτήσεων. Ο μεταγλωττιστής απαιτεί το try να βρίσκεται σε περιβάλλον όπου το σφάλμα μπορεί να πιαστεί.

try? — μετατροπή σε Optional

try? μετατρέπει το αποτέλεσμα της throwing συνάρτησης σε Optional. Αν η συνάρτηση εκτοξεύσει σφάλμα, το try? επιστρέφει nil, διαφορετικά — Optional με την επιτυχημένη τιμή. Χρήσιμο για κλήσεις όπου το σφάλμα μπορεί να αγνοηθεί, αλλά χρειάζεται ένας δείκτης επιτυχίας.

try! — εξαναγκασμένη εκτέλεση

try! καταστέλλει τη διαχείριση σφαλμάτων. Αν η throwing συνάρτηση εκτοξεύσει σφάλμα, η εφαρμογή τερματίζεται με σφάλμα runtime. Χρησιμοποιήστε το try! μόνο όταν είστε απολύτως βέβαιοι ότι το σφάλμα είναι αδύνατο — για παράδειγμα, κατά τη φόρτωση ενός ενσωματωμένου πόρου.

swift
// try? — αγνοούμε το σφάλμα, λαμβάνουμε nil σε βλάβη
if let data = try? Data(contentsOf: url) {
    processData(data)
}

// try! — μόνο αν το σφάλμα είναι εγγυημένα αδύνατο
let bundled = try! String(contentsOfFile: "Assets/default.txt")

// try — τυπική επιλογή στο do-catch
do {
    let result = try performNetworkRequest()
    updateUI(result)
} catch {
    showError(error)
}

Do-Catch στην ανάπτυξη iOS: πρακτικά παραδείγματα

Το Do-Catch χρησιμοποιείται ενεργά στην ανάπτυξη iOS για εργασία με συστήματα API. Ας εξετάσουμε τυπικά σενάρια: εργασία με σύστημα αρχείων, Core Data και αιτήματα δικτύου.

Σύστημα αρχείων

Πολλές μέθοδοι του FileManager είναι throwing. Το Do-Catch επιτρέπει τη σωστή διαχείριση απουσίας αρχείου, κατειλημμένου πόρου ή έλλειψης δικαιωμάτων.

Αιτήματα δικτύου με Codable

Η ανάλυση JSON μέσω JSONDecoder — μια throwing λειτουργία. Το Do-Catch πιάνει σφάλματα αποκωδικοποίησης και βλάβες δικτύου ξεχωριστά, παρέχοντας στο χρήστη το ακριβές κείμενο σφάλματος.

swift
struct User: Codable {
    let id: Int
    let name: String
}

func fetchUser(id: Int) async throws -> User {
    let url = URL(string: "https://api.example.com/users/\(id)")!
    let (data, _) = try await URLSession.shared.data(from: url)
    return try JSONDecoder().decode(User.self, from: data)
}

// Κλήση με διαχείριση
do {
    let user = try await fetchUser(id: 42)
    showUser(user)
} catch let error as URLError {
    showNetworkAlert(error)
} catch let error as DecodingError {
    showParseError(error)
} catch {
    showGenericError(error)
}

Συνηθισμένα λάθη κατά τη χρήση Do-Catch

Οι προγραμματιστές, ειδικά όσοι μεταβαίνουν από άλλες γλώσσες, συχνά κάνουν χαρακτηριστικά λάθη όταν χρησιμοποιούν το Do-Catch. Ας εξετάσουμε τα πιο συνηθισμένα.

  • Ξεχασμένο try — κλήση throwing συνάρτησης χωρίς try οδηγεί σε σφάλμα μεταγλώττισης. Η Swift δεν επιτρέπει σιωπηρή αγνόηση σφαλμάτων.
  • Άδειο catch — μπλοκ catch χωρίς διαχείριση κρύβει το σφάλμα. Πάντα καταγράφετε ή διαχειρίζεστε το σφάλμα, ακόμα κι αν φαίνεται αδύνατο.
  • Catch χωρίς αντιστοίχιση — ένα γενικό catch για όλα τα σφάλματα στερεί τα πλεονεκτήματα ασφάλειας τύπων. Διαχωρίστε τη διαχείριση κατά τύπους μέσω πολλαπλών μπλοκ.
  • Υπερβολική χρήση try! — το try! σε κώδικα παραγωγής είναι πηγή απροσδόκητων crash. Χρησιμοποιήστε μόνο για ενσωματωμένους πόρους ή δοκιμές.

Συχνές Ερωτήσεις

Σε τι διαφέρει το Do-Catch στη Swift από το try-catch σε άλλες γλώσσες;

Στη Swift το σφάλμα είναι μια τιμή που αντιστοιχεί στο πρωτόκολλο Error, όχι exception με ξετύλιγμα στοίβας. Οι throwing συναρτήσεις πρέπει να σημειώνονται ρητά με throws, και ο μεταγλωττιστής απαιτεί try κατά την κλήση — αυτό εξαλείφει σφάλματα που δεν έχουν διαχειριστεί στο στάδιο μεταγλώττισης.

Μπορεί να χρησιμοποιηθεί το Do-Catch με async/await;

Ναι, οι async συναρτήσεις μπορούν επίσης να είναι throws, και το do-catch λειτουργεί για αυτές. Η κλήση async throwing συνάρτησης απαιτεί try await μέσα σε μπλοκ do. Αυτός είναι ο τυπικός τρόπος διαχείρισης σφαλμάτων σε ασύγχρονο κώδικα Swift.

Πώς να διαχειριστώ ένα σφάλμα χωρίς do-catch;

Υπάρχουν εναλλακτικές: το try? μετατρέπει το σφάλμα σε nil, το try! προκαλεί crash σε σφάλμα, και το rethrows επιτρέπει τη διάδοση σφάλματος από closure. Το do-catch παραμένει ο κύριος τρόπος ρητής διαχείρισης.

Μπορεί μια συνάρτηση να εκτοξεύει διαφορετικούς τύπους σφαλμάτων;

Η Swift δεν τυποποιεί τα εκτοξευόμενα σφάλματα — οποιαδήποτε throwing συνάρτηση μπορεί να εκτοξεύσει οποιονδήποτε τύπο που αντιστοιχεί στο Error. Διαχωρίστε τη διαχείριση μέσω αντιστοίχισης στο catch με συγκεκριμένους τύπους σφαλμάτων.

Αξίζει να τυλίγουμε όλα τα σφάλματα σε δικό μας προσαρμοσμένο τύπο;

Ναι, αυτή είναι η βέλτιστη πρακτική. Ορίστε το AppError ως enum με επιβεβαίωση Error και μετατρέψτε τα συστημικά σφάλματα σε σφάλματα τομέα. Αυτό ενοποιεί τη διαχείριση και απομονώνει το επίπεδο εφαρμογής από συστημικές λεπτομέρειες.

Σύνοψη

  • Do-Catch — κατασκευή Swift για διαχείριση σφαλμάτων με υποχρεωτική σήμανση throws στις συναρτήσεις και try κατά την κλήση.
  • Τα σφάλματα Swift — τιμές που αντιστοιχούν στο πρωτόκολλο Error, όχι εξαιρέσεις με ξετύλιγμα στοίβας, που δίνει μηδενική επιβάρυνση όταν δεν υπάρχει βλάβη.
  • Πολλαπλά catch επιτρέπουν ξεχωριστή διαχείριση διαφορετικών τύπων σφαλμάτων με pattern-matching ανάλογο του switch.
  • Το try? μετατρέπει το σφάλμα σε nil για απλά σενάρια, το try! — εξαναγκασμένη κλήση με κίνδυνο crash, που χρησιμοποιείται μόνο για εγγυημένα επιτυχημένες λειτουργίες.
  • Do-Catch με async/await — ο τυπικός τρόπος διαχείρισης σφαλμάτων σε ασύγχρονο κώδικα Swift με χρήση try await.
  • Αποφύγετε τα άδεια catch και την υπερβολική χρήση try! — αυτό κρύβει σφάλματα και οδηγεί σε απροσδόκητες βλάβες στην παραγωγή.

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης