Suche…


Bemerkungen

Weitere Informationen zu Fehlern finden Sie unter Die Programmiersprache Swift .

Fehler beim Umgang mit Grundlagen

Funktionen in Swift können Werte zurückgeben, Fehler oder beides auslösen:

func reticulateSplines()                // no return value and no error
func reticulateSplines() -> Int         // always returns a value
func reticulateSplines() throws         // no return value, but may throw an error
func reticulateSplines() throws -> Int  // may either return a value or throw an error

Jeder Wert, der dem ErrorType-Protokoll entspricht (einschließlich NSError-Objekten), kann als Fehler ausgegeben werden. Aufzählungen bieten eine bequeme Möglichkeit, benutzerdefinierte Fehler zu definieren:

2,0 2,2
enum NetworkError: ErrorType {
    case Offline
    case ServerError(String)
}
3,0
enum NetworkError: Error {
    // Swift 3 dictates that enum cases should be `lowerCamelCase`
    case offline
    case serverError(String)
}

Ein Fehler weist auf einen nicht schwerwiegenden Fehler während der Programmausführung hin und wird mit den speziellen Kontrollflusskonstrukten do / catch , throw und try .

func fetchResource(resource: NSURL) throws -> String {
    if let (statusCode, responseString) = /* ...from elsewhere...*/ {
        if case 500..<600 = statusCode {
            throw NetworkError.serverError(responseString)
        } else {
            return responseString
        }
    } else {
        throw NetworkError.offline
    }
}

Fehler können mit do / catch abgefangen werden:

do {
    let response = try fetchResource(resURL)
    // If fetchResource() didn't throw an error, execution continues here:
    print("Got response: \(response)")
    ...
} catch {
    // If an error is thrown, we can handle it here.
    print("Whoops, couldn't fetch resource: \(error)")
}

Jede Funktion, die einen Fehler auslösen kann, muss mit try , try? aufgerufen werden try? oder try! :

// error: call can throw but is not marked with 'try'
let response = fetchResource(resURL)

// "try" works within do/catch, or within another throwing function:
do {
    let response = try fetchResource(resURL)
} catch {
    // Handle the error
}

func foo() throws {
    // If an error is thrown, continue passing it up to the caller.
    let response = try fetchResource(resURL)
}

// "try?" wraps the function's return value in an Optional (nil if an error was thrown).
if let response = try? fetchResource(resURL) {
    // no error was thrown
}

// "try!" crashes the program at runtime if an error occurs.
let response = try! fetchResource(resURL)

Verschiedene Fehlertypen abfangen

Lassen Sie uns einen eigenen Fehlertyp für dieses Beispiel erstellen.

2.2
enum CustomError: ErrorType {
    case SomeError
    case AnotherError
}

func throwing() throws {
    throw CustomError.SomeError
}
3,0
enum CustomError: Error {
    case someError
    case anotherError
}

func throwing() throws {
    throw CustomError.someError
}

Die Do-Catch-Syntax ermöglicht das Abfangen eines ausgelösten Fehlers und erstellt automatisch einen konstanten benannten error , der im catch Block verfügbar ist:

do {
    try throwing()
} catch {
    print(error)
}

Sie können eine Variable auch selbst deklarieren:

do {
    try throwing()
} catch let oops {
    print(oops)
}

Es ist auch möglich, verschiedene catch Anweisungen zu catch . Dies ist praktisch, wenn im Do-Block mehrere Arten von Fehlern ausgegeben werden können.

Hier versucht der Do-Catch zuerst, den Fehler als CustomError und dann als NSError wenn der benutzerdefinierte Typ nicht übereinstimmt.

2.2
do {
    try somethingMayThrow()
} catch let custom as CustomError {
    print(custom)
} catch let error as NSError {
    print(error)
}
3,0

In Swift 3 muss nicht explizit auf NSError heruntergespielt werden.

do {
    try somethingMayThrow()
} catch let custom as CustomError {
    print(custom)
} catch {
    print(error)
}

Catch- und Switch-Muster für explizite Fehlerbehandlung

class Plane {
    
    enum Emergency: ErrorType {
        case NoFuel
        case EngineFailure(reason: String)
        case DamagedWing
    }

    var fuelInKilograms: Int

    //... init and other methods not shown

    func fly() throws {
        // ...
        if fuelInKilograms <= 0 {
            // uh oh...
            throw Emergency.NoFuel
        }
    }

}

In der Kundenklasse:

let airforceOne = Plane()
do {
    try airforceOne.fly()
} catch let emergency as Plane.Emergency {
    switch emergency {
    case .NoFuel:
        // call nearest airport for emergency landing
    case .EngineFailure(let reason):
        print(reason) // let the mechanic know the reason
    case .DamagedWing:
        // Assess the damage and determine if the president can make it
    }
}

Deaktivieren der Fehlerausbreitung

Die Macher von Swift haben viel Wert darauf gelegt, die Sprache ausdrucksstark zu gestalten, und Fehlerbehandlung ist genau das, ausdrucksstark. Wenn Sie versuchen, eine Funktion aufzurufen, die einen Fehler auslösen kann, muss vor dem Funktionsaufruf das Schlüsselwort try stehen. Das try-Keyword ist nicht magisch. Alles, was er tut, ist, den Entwickler auf die Wurffähigkeit der Funktion aufmerksam zu machen.

Im folgenden Code wird beispielsweise die Funktion loadImage (atPath :) verwendet, die die Bildressource an einem bestimmten Pfad lädt oder einen Fehler ausgibt, wenn das Bild nicht geladen werden kann. In diesem Fall wird zur Laufzeit kein Fehler ausgegeben, da das Image mit der Anwendung ausgeliefert wird. Daher sollte die Fehlerweiterleitung deaktiviert werden.

let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")

Erstellen Sie einen benutzerdefinierten Fehler mit lokalisierter Beschreibung

Erstellen Sie eine enum benutzerdefinierter Fehler

enum RegistrationError: Error {
    case invalidEmail
    case invalidPassword
    case invalidPhoneNumber
}

Erstellen Sie eine extension von RegistrationError , um die lokalisierte Beschreibung zu behandeln.

extension RegistrationError: LocalizedError {
    public var errorDescription: String? {
        switch self {
        case .invalidEmail:
            return NSLocalizedString("Description of invalid email address", comment: "Invalid Email")
        case .invalidPassword:
            return NSLocalizedString("Description of invalid password", comment: "Invalid Password")
        case .invalidPhoneNumber:
            return NSLocalizedString("Description of invalid phoneNumber", comment: "Invalid Phone Number")
        }
    }
}

Handle Fehler:

let error: Error = RegistrationError.invalidEmail
print(error.localizedDescription)


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow