Skip to content

Classes, part 4

Prepared and tested with Xcode 8.3 and Swift 3.1

In this tutorial we cover the following topics


Error handling

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.

A good choice to represent a group of related error types are enumerations.

A throw keyword is used to bring to life an error.

When an error is thrown, some surrounding piece of code must be responsible for handling it. There are four ways to handle errors in Swift.

  1. Error can be propagated from a function to the code that calls that function.
  2. Error can be handled with do-catch statement.
  3. Error can be handled as an optional value.
  4. Error propagation can be disabled and its call wraped in a runtime assertion that no error will be thrown.


Error propagation

We use the throws keyword to indicate that a function, method, or initializer can throw an error. A function marked this way is called a throwing function. Only throwing functions can propagate errors. Any errors thrown inside a nonthrowing function must be handled inside that function.


Error handling with do-catch

General form of do-catch statement is very rich

and can be used as the following example shows


Error type 0


Error handling with optionals

We use 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 nil.


Error propagation disable

When we are sure that throwing function or method will not throw an error at runtime we can write try! to disable error propagation and wrap the call in a runtime assertion that no error will be thrown. Note that if an error actually occurs and is thrown, we will get a runtime error.


Error cleaning

In Java very common statements sequence is try-catch-finally because
The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated. [finally doc]

In Swift there is very similar statemen: defer. It is used to execute a set of statements just before code execution leaves the current block of code. As in Java with this statement we can do any necessary cleanup that should be performed regardless of how execution leaves the current block of code - whether it leaves because an error was thrown or because of a statement such as return or break or even quite natural without any errors or jumps. The most basic example given in all tutorials is when we want to ensure that file descriptors are closed or manually allocated memory is freed.

A defer statement defers execution until the current scope is exited. The deferred statements may not contain any code that would transfer control out of the statements, such as a break or a return statement, or by throwing an error. Deferred actions are executed in the reverse of the order that they’re written in our source code. That is, the code in the first defer statement executes last, the code in the second defer statement executes second to last, and so on. The last defer statement in source code order executes first.


1
2
5
3
7
9
fatal error: Error raised at top level:
[...]

If you want to see more examples, you can read Magical Error Handling in Swift