In Swift, errors can be any type that conforms to the Error protocol.
The Error protocol doesn't have any required functions or properties.
It means that any class, enum, or structure can be an error.
When your code encounters an error, you throw an error.
For example, let's define an enumeration for problems that can relate to a car.
By making the enumeration an Error, we can throw it as an error:
enum CarError : Error { case noGas case tooSlow case tooFast(amount:Float) }
Functions that can throw errors must be marked with the throws keyword, which goes after the function's return type:
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 } }
When you call any function, method, or initializer that throws, you are required to wrap it in a do-catch block.
In the do block, you call the methods that may potentially throw errors.
Each time you do this, you preface the potentially throwing call with try.
If the method call throws an error, the do block stops executing and the catch clause runs:
do { let v = try Car(amount: 5) try v.moreGas(amount: 5) try v.lessGas(amount: 11) } catch let error as CarError { switch (error) { case .noGas: print("No Gas!") case .tooSlow: print("to slow!") case .tooFast(let amount): print("too fast") } } catch let error { // (Optional:) Catch other types of errors }