Sobes.tech
Junior

Πώς ανιχνεύετε σφάλματα στο Swift;

sobes.tech AI

Απάντηση από AI

Στα Swift, τα σφάλματα αντιμετωπίζονται με ένα σύστημα διαχείρισης σφαλμάτων που βασίζεται στις λέξεις-κλειδιά throw, throws, try και το μπλοκ do-catch.

  1. Ορισμός συναρτήσεων που μπορούν να ρίξουν σφάλματα: Χρησιμοποιείται η λέξη-κλειδί throws μετά τα ορίσματα της συνάρτησης.

    enum DataError: Error {
        case emptyData
        case invalidFormat
    }
    
    func processData(input: String) throws -> String {
        guard !input.isEmpty else {
            throw DataError.emptyData // Ρίχνουμε σφάλμα
        }
        // ... λογική επεξεργασίας δεδομένων...
        if input == "invalid" {
             throw DataError.invalidFormat
        }
        return "Επεξεργασμένο: \(input)"
    }
    
  2. Κάλεσμα συναρτήσεων που μπορούν να ρίξουν σφάλματα: Χρησιμοποιείται η λέξη-κλειδί try.

    do { // Μπλοκ για διαχείριση σφαλμάτων
        let result = try processData(input: "valid data")
        print(result) // "Επεξεργασμένο: valid data"
    } catch { // Μπλοκ για πιάσιμο σφαλμάτων
        print("Παρουσιάστηκε σφάλμα: \(error)")
    }
    
  3. Πιάσιμο συγκεκριμένων τύπων σφαλμάτων: Στο μπλοκ catch μπορεί να δηλωθεί συγκεκριμένος τύπος σφάλματος.

    do {
        let result = try processData(input: "")
        print(result)
    } catch DataError.emptyData {
        print("Τα δεδομένα είναι κενά, παρακαλώ δώστε εισαγωγή.")
    } catch DataError.invalidFormat {
        print("Ο μορφότυπος των δεδομένων είναι άκυρος.")
    } catch { // Πιάσιμο οποιωνδήποτε άλλων σφαλμάτων
        print("Απρόβλεπτο σφάλμα: \(error)")
    }
    
  4. Μπλοκ defer: Εκτελείται αμέσως πριν από την έξοδο από το τρέχον πεδίο ορατότητας, ανεξάρτητα από το αν υπήρξε σφάλμα ή όχι. Συχνά χρησιμοποιείται για καθαρισμό πόρων.

    func openFile(_ filename: String) throws -> String {
        // Υποθέτουμε ότι ανοίγει ένα αρχείο και επιστρέφει το περιεχόμενό του
        print("Άνοιγμα αρχείου: \(filename)")
        // ... λογική ανοίγματος...
    
        defer {
            // Αυτός ο κώδικας θα εκτελεστεί πριν από την έξοδο από τη συνάρτηση,
            // ακόμα και αν προκύψει σφάλμα
            print("Κλείσιμο αρχείου: \(filename)")
        }
    
        // ... επεξεργασία αρχείου ...
        if filename == "error.txt" {
           throw DataError.invalidFormat // Ρίχνουμε σφάλμα
        }
    
        return "Περιεχόμενο αρχείου"
    }
    
    do {
        let content = try openFile("data.txt")
        print(content)
    } catch {
        print("Σφάλμα στη διαχείριση αρχείου: \(error)")
    }
    
  5. Προαιρετικό try?: Επιστρέφει προαιρετική τιμή. Αν η συνάρτηση ρίξει σφάλμα, το try? επιστρέφει nil.

    let processedResult = try? processData(input: "") // processedResult θα είναι nil
    let validResult = try? processData(input: "abc") // validResult θα είναι προαιρετικό String με την τιμή "Processed: abc"
    
  6. Εξαναγκασμένη εξαγωγή try!: Χρησιμοποιείται όταν είστε βέβαιοι ότι δεν θα προκύψει σφάλμα. Αν προκύψει, η εφαρμογή θα τερματίσει απότομα. Χρησιμοποιείτε με προσοχή.

    // Χρησιμοποιήστε μόνο αν είστε 100% βέβαιοι ότι η συνάρτηση δεν θα ρίξει σφάλμα
    let result = try! processData(input: "πάντα έγκυρη εισαγωγή")
    

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