Sök…


Anmärkningar

Mer information om fel finns i The Swift Programming Language .

Fel vid hantering av grunderna

Funktioner i Swift kan returnera värden, kastfel eller båda:

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

Alla värden som överensstämmer med ErrorType-protokollet (inklusive NSError-objekt) kan kastas som ett fel. Uppräkningar ger ett bekvämt sätt att definiera anpassade fel:

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

Ett fel indikerar ett icke-dödligt fel under programutförandet och hanteras med de specialiserade kontrollflödeskonstruktionerna do / catch , throw och 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
    }
}

Fel kan fångas med 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)")
}

Varje funktion som kan kasta ett fel måste kallas med try , try? , eller 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)

Att fånga olika feltyper

Låt oss skapa vår egen feltyp för det här exemplet.

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
}

Syntaxen Do-Catch gör det möjligt att fånga ett kastat fel och skapar automatiskt ett konstant namngivet error tillgängligt i catch :

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

Du kan också själv förklara en variabel:

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

Det är också möjligt att kedja olika catch . Detta är bekvämt om flera typer av fel kan kastas i Do-blocket.

Här kommer Do-Catch först att försöka kasta felet som en CustomError , sedan som en NSError om den anpassade typen inte matchades.

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

I Swift 3 behöver du inte uttryckligen nedställa till NSError.

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

Fånga och växla mönster för explicit felhantering

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

}

I klientklassen:

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

Inaktiverar felförökning

Skaparna av Swift har lagt mycket uppmärksamhet på att göra språket uttrycksfullt och felhantering är exakt det, uttrycksfullt. Om du försöker åberopa en funktion som kan kasta ett fel måste funktionssamtalet föregås av försöksordet. Tryckordet är inte magiskt. Allt det gör är att göra utvecklaren medveten om funktionens kastförmåga.

Till exempel använder följande kod en loadImage (atPath :) -funktion, som laddar bildresursen på en given bana eller kastar ett fel om bilden inte kan laddas. I det här fallet, eftersom bilden levereras med applikationen, kommer inga fel att kastas vid körning, så det är lämpligt att inaktivera felutbredning.

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

Skapa anpassat fel med lokaliserad beskrivning

Skapa enum av anpassade fel

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

Skapa extension av RegistrationError att hantera den lokaliserade beskrivningen.

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

Hanteringsfel:

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


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow