Introduction

Consider the following code:

enum CarError  : Error { 
    case noGas 
    case tooSlow 
    case tooFast(amount:Float) 
} 
class Car { 
    private (set) var speed  : Float = 0.0 

    init(amount:Float) throws { 
        guard amount > 0 else { 
            throw CarError.tooSlow 
        } 
        speed = amount 
    } 
    func moreGas(amount: Float) throws { 
        guard amount > 0 else { 
            throw CarError.tooFast(amount: amount) 
        } 
        speed += amount 
    } 
    func lessGas(amount  : Float) throws { 
        guard amount > 0 else { 
            throw CarError.tooFast(amount: amount) 
        } 
        guard speed >= amount else { 
            throw CarError.noGas 
        } 
        speed -= amount 
    } 
} 

try?

If you preface a call to something that can throw an error with try?, and it does throw an error, the result will be nil:

let v = try? Car(amount: -50) // nil 

The return type of any call that you try? will be an optional.

If you call a method with try!, and it throws an error, your program will simply crash.

This has the same effect as using try? to receive an optional and then using the force-unwrap operator ! on that optional:

let v = try! Car(amount: 50) 
// this call will exit or crash if we put in an invalid amount 

The try? and try! statements do not need to be in a do-catch block.

If you do put them in do-catch block, any errors won't be caught by the catch block.

They'll still just either evaluate to nil or cause a crash.

Related Topic