Sobes.tech
Junior

Jak wykrywać błędy w Swift?

sobes.tech AI

Odpowiedź od AI

W Swift błędy są przechwytywane za pomocą systemu obsługi błędów opartego na użyciu słów kluczowych throw, throws, try oraz bloku do-catch.

  1. Deklaracja funkcji, które mogą rzucać błędy: Używa się słowa kluczowego throws po parametrach funkcji.

    enum DataError: Error {
        case emptyData
        case invalidFormat
    }
    
    func processData(input: String) throws -> String {
        guard !input.isEmpty else {
            throw DataError.emptyData // Rzucamy błąd
        }
        // ...logika przetwarzania danych...
        if input == "invalid" {
             throw DataError.invalidFormat
        }
        return "Przetworzono: \(input)"
    }
    
  2. Wywołanie funkcji, które mogą rzucać błędy: Używa się słowa kluczowego try.

    do { // Blok obsługi błędów
        let result = try processData(input: "prawidłowe dane")
        print(result) // "Przetworzono: prawidłowe dane"
    } catch { // Blok przechwytywania błędów
        print("Wystąpił błąd: \(error)")
    }
    
  3. Przechwytywanie określonych typów błędów: W bloku catch można wskazać konkretny typ błędu do przechwycenia.

    do {
        let result = try processData(input: "")
        print(result)
    } catch DataError.emptyData {
        print("Dane są puste, proszę podać dane wejściowe.")
    } catch DataError.invalidFormat {
        print("Format danych jest nieprawidłowy.")
    } catch { // Przechwyć wszystkie inne błędy
        print("Nieoczekiwany błąd: \(error)")
    }
    
  4. Blok defer: Wykonuje się bezpośrednio przed wyjściem z bieżącego zakresu, niezależnie od tego, czy wystąpił błąd, czy nie. Często używany do zwalniania zasobów.

    func openFile(_ filename: String) throws -> String {
        // Załóżmy, że to otwiera plik i zwraca jego zawartość
        print("Otwieranie pliku \(filename)")
        // ... logika otwierania ...
    
        defer {
            // Ten kod zostanie wykonany przed wyjściem z funkcji,
            // nawet jeśli wystąpi błąd
            print("Zamykanie pliku \(filename)")
        }
    
        // ... przetwarzanie pliku ...
        if filename == "error.txt" {
           throw DataError.invalidFormat // Rzucamy błąd
        }
    
        return "Zawartość pliku"
    }
    
    do {
        let content = try openFile("data.txt")
        print(content)
    } catch {
        print("Błąd obsługi pliku: \(error)")
    }
    
  5. Opcjonalny try?: Zwraca wartość opcjonalną. Jeśli funkcja rzuci błąd, try? zwraca nil.

    let processedResult = try? processData(input: "") // processedResult będzie nil
    let validResult = try? processData(input: "abc") // validResult będzie opcjonalnym String z wartością "Przetworzono: abc"
    
  6. Wymuszone try!: Używa się, gdy jest się pewnym, że błąd nie wystąpi. Jeśli jednak wystąpi, aplikacja zostanie nieoczekiwanie zakończona. Używaj ostrożnie.

    // Używaj tylko, jeśli jesteś w 100% pewien, że funkcja nie rzuci błędu
    let result = try! processData(input: "zawsze poprawne wejście")
    

System oparty na do-catch jest bardziej jawny i bezpieczny w obsłudze błędów w porównaniu do tradycyjnych wyjątków w innych językach, ponieważ wymaga jawnego deklarowania funkcji, które mogą rzucać błędy (throws), oraz jawnego obsługiwania tych błędów podczas wywołania (try, do-catch).