Swift Error Throwing and Catching


  • Share on Pinterest

Errors are bad, but there are times you will want to create an error in order to deal with a situation gracefully rather than having your application do wild uncontrolled actions like freezing or closing. That is where throwing an error comes in, no it's not like a tantrum on a fake reality show, it's a real thing in Swift! Why don't we go throw somethings around to discover how it works.

Time to open another wonderful Swift playground and crank up some code. The examples below are designed to be simple demonstrations of the syntax structure when using errors, arguably you would never have simple functions like these in your code. Any time you have code that could cause an error you will want to wrap it in a do try. Good examples are loading external files or URL's.

First I am going to create an enumeration to hold my custom error types.

enum ErrorList: ErrorType {
    case Fatal
    case Major
    case Minor
}

Now I am going to create a function that uses the enumeration for throwing an error. The function below takes two integer arguments and compares them. If the two numbers do not match then we throw an error of type ErrorList.Major. Otherwise a String is returned. Note something new here, we indicate that the function throws an error. You put throws after the argument.

func theFunction(a:Int, b:Int) throws -> String {
    If (a != b) {
        Throw ErrorList.Major
    }
    return "They match"
}

To call the function we use a do catch, in other languages you probably have seen this as a try catch statement. The catch statement automatically gets the error object that we use within the body, in this case a simple print statement.

do {
    try theFunction(1, b: 1)
} catch {
    // You would probably have other code here
    // but for this example we will use the print statement
    print(error)
}

You can create more than one catch block, this is perfect for handling multiple outcomes. You may for example want to catch a Fatal and do something different than say a Minor error.

func nonMatch(a:Int, b:Int) throws -> String {
    if (a == b) {
        return "They Match!"
    } else if ( a > b) {
        throw ErrorList.Fatal
    } else {
        throw ErrorList.Minor
    }
}

do {
    try nonMatch(10, b: 10)
}

catch ErrorList.Fatal {
    print("Fatal Error: The Ship is Sinking!")
}
catch ErrorList.Minor {
    print("Minor Error: Iceberg Ahead!")
}
catch {
    print(error)
}

As you can see you create the specific catches you want to handle different and create a generic to capture everything else.

You can also pass arguments to the error types. For example here is a new error enum containing an error that accepts arguments.

enum NewErrors: ErrorType {
    case InvalidNumber
    case LowCount(numNeeded: Int)
}

Now the error type LowCount can accept an integer argument.

throw NewErrors.LowCount(numNeeded: 10)

This is a quick overview of how you can start using errors to your advantage in applications, I have purposefully kept the examples simple so those of you who have never used throw or catch before can start to play with them.

For further details you can read the Apple documentation here.