Representing and Throwing Errors
In Swift, errors are represented by values of types that conform to the
Error protocol. This empty protocol indicates that a type can be used for error handling.
Error handling in Swift does not involve unwinding the call stack, a process that can be computationally expensive.As such, the performance characteristics of a throw statement are comparable to those of a return statement.
There are four ways to handle errors in Swift. You can:
Propagate the error from a function to the code that calls that function
Use a throwing function
func canThrowErrors() throws -> String. Any code that calls this method must either handle the errors—using a
try!—or continue to propagate them.
Handle the error using a do-catch statement
catch clauses don’t have to handle every possible error that the code in its
do clause can throw. If none of the
catch clauses handle the error, the error propagates to the surrounding scope. However, the error must be handled by some surrounding scope.
Handle the error as an optional value
try? to handle an error by converting it to an optional value. If an error is thrown while evaluating the
try? expression, the value of the expression is
let x = try? someThrowingFunction()
Assert that the error will not occur
Sometimes you know a throwing function or method won’t, in fact, throw an error at runtime. On those occasions, you can write
try! before the expression to disable error propagation and wrap the call in a runtime assertion that no error will be thrown. If an error actually is thrown, you’ll get a runtime error.
The Result Type
According to Matt Gallagher’s post:
Examples of scenarios you might want to handle where Swift’s error handling won’t help include:
- results passed between threads
- results asynchronously delivered to the current thread
- results retained for any duration
- results passed into a function rather than out of a function
The obvious candidate in these other scenarios is a
Result type. Where Swift’s error handling encapsulates the composite nature of error handling by using “value” and “error” return paths from a function, a
Result type embeds the “value” or “error” directly into a composite data type:
Meaningful Composite Errors by Ian Keen