Zoeken…


Opmerkingen

Zie De snelle programmeertaal voor meer informatie over fouten.

Fout bij het omgaan met basisprincipes

Functies in Swift kunnen waarden, foute fouten of beide retourneren:

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

Elke waarde die voldoet aan het ErrorType-protocol (inclusief NSError-objecten) kan als een fout worden gegenereerd. Opsommingen bieden een handige manier om aangepaste fouten te definiëren:

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)
}

Een fout duidt op een niet-fatale fout tijdens de uitvoering van het programma en wordt afgehandeld met de gespecialiseerde control-flow-constructies do / catch , throw en 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
    }
}

Fouten kunnen worden gevangen met do / catch :

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)")
}

Elke functie die een fout kan veroorzaken, moet worden opgeroepen met try , try? of 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)

Verschillende soorten fouten opvangen

Laten we voor dit voorbeeld ons eigen fouttype maken.

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
}

De syntaxis van Do-Catch maakt het mogelijk een gegooide fout op te vangen en maakt automatisch een constante benoemde error beschikbaar in het catch :

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

Je kunt ook zelf een variabele declareren:

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

Het is ook mogelijk om verschillende catch koppelen. Dit is handig als verschillende soorten fouten in het Do-blok kunnen worden veroorzaakt.

Hier zal de Do-Catch eerst proberen de fout als een CustomError , en vervolgens als een NSError als het aangepaste type niet overeenkomt.

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

In Swift 3 is het niet nodig om expliciet te downcasten naar NSError.

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

Patroon vangen en schakelen voor expliciete foutafhandeling

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 de klantklasse:

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
    }
}

Foutpropagatie uitschakelen

De makers van Swift hebben veel aandacht besteed aan het expressief maken van de taal en foutafhandeling is precies dat, expressief. Als u probeert een functie op te roepen die een fout kan veroorzaken, moet de functieaanroep worden voorafgegaan door het sleutelwoord try. Het try-trefwoord is niet magisch. Het enige wat het doet, is de ontwikkelaar bewust maken van het werpvermogen van de functie.

De volgende code gebruikt bijvoorbeeld een functie loadImage (atPath :), die de afbeeldingsresource op een bepaald pad laadt of een foutmelding geeft als de afbeelding niet kan worden geladen. In dit geval wordt er tijdens het uitvoeren van de afbeelding geen fout gegenereerd omdat de afbeelding wordt meegeleverd met de toepassing. Het is daarom raadzaam de foutpropagatie uit te schakelen.

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

Maak een aangepaste fout met gelokaliseerde beschrijving

Maak enum aangepaste fouten

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

Maak een extension van RegistrationError om de gelokaliseerde beschrijving af te handelen.

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")
        }
    }
}

Omgaan met fout:

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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow