Swift Error Handling

An error (exception) is an unexpected event that occurs during program execution. For example,

var numerator = 10
var denominator = 0

// try to divide a number by 0
var result = numerator / denominator // error code

Here, we are trying to divide a number. So this type of error causes the abnormal termination of the program.


Steps For Error Handling in Swift

  1. Create an enum that represents the types of errors.
  2. Create a throwing function using the throws keyword.
  3. Call the function using the try keyword.
  4. Wrap the code with try in the do {...} block and add the catch {...} block to handle all errors.

1. Create enum of Errors

In Swift, we need to create an enum that represents the type of errors we may encounter while writing the program.

The enum we create must conform to the Error protocol so that we can throw an error value inside the function.

Let's see an example,

enum DivisionError: Error {
  case dividedByZero
}

Here, we have created an enum named DivisionError with the value dividedByZero.

Since DivisionError conforms to the Error protocol, we'll now be able to throw the error value of the enum.


2. Create a Throwing Function

In order to throw errors, we need to create a throwing function using the throws keyword.

Then we use the throw statement inside the function to throw a particular error represented by the enum. For example,

// create throwing function using throws keyword
func division(numerator: Int, denominator: Int) throws {

// throw error if divide by 0
  if denominator == 0 {
    throw DivisionError.dividedByZero
  }
  ...     
}

Here, we have created a throwing function named division() using the throws keyword. The function throws the dividedByZero value of the DivisionError enum if denominator == 0

Now, based on the value passed during the function call, the function throws an error if the error condition is met.

Note: The throw keyword has the same effect as the return keyword. return returns some value from the function, whereas throw returns error value from the function.


3. Function Call Using try Keyword

In Swift, we use the try keyword while calling the throwing function. It indicates that a function can throw an error. For example,

// call throwing function using try keyword
try division(numerator: 10, denominator: 0)

However, the error handling process is still incomplete. If we run the program now, we'll get an error message: An error was thrown and was not caught

So, in order to catch the thrown error, we use the do-catch statement.


4. Handling Errors Using do-catch Statement

In Swift, we wrap the try code in the do block and add the catch block to handle all errors. For example,

do {
  try division(numerator: 10, denominator: 0)
  ...
}

catch DivisionError.dividedByZero {
  // statement
}

Here, we have called the throwing function division() from within the do block and attached the catch block to catch the error in case the function throws one.

The above catch block is executed based on the enum value of DivisionError.

This is the final step to handle possible errors that may occur in our program.


Example: Swift Error Handling

// create an enum with error values
enum DivisionError: Error {

  case dividedByZero
}

// create a throwing function using throws keyword
func division(numerator: Int, denominator: Int) throws {

  // throw error if divide by 0
  if denominator == 0 {
    throw DivisionError.dividedByZero
  }
    
  else {
    let result = numerator / denominator
    print(result)
  }
}

// call throwing function from do block
do {
  try division(numerator: 10, denominator: 0)
  print("Valid Division")
}

// catch error if function throws an error
catch DivisionError.dividedByZero {
  print("Error: Denominator cannot be 0")
}

Output

Error: Denominator cannot be 0

In the above example,

  • DivisionError is an enum
  • division() is a throwing function
  • the do-catch statement handles the error

We have used try to pass values to the throwing function

try division(numerator: 10, denominator: 0)

to check if the passed values meet the error condition or not.

If the error condition is

  • met - the throwing function throws the error, which is caught by the catch block.
  • not met - the else statement inside throwing function and print statement inside the do block are executed.

Disable Error Handling

In Swift, sometimes we can be confident that the throwing function won't throw an error at runtime.

In that case, we can write try! during the function call to disable the error handling. For example,

enum DivisionError: Error {
  
  case dividedByZero
}

func division(numerator: Int, denominator: Int) throws {
  if denominator == 0 {
    throw DivisionError.dividedByZero
  }
    
  else {
    let result = numerator / denominator
    print("Result:", result)
  }
}

// disable error handling
try! division(numerator: 10, denominator: 5)

Output

Result: 2

In the above example, we have used try! during the function call to disable the error handling.

try! division(numerator: 10, denominator: 5)

Here, since we have assigned value 5 to denominator, we know that the program will not throw an error. So we have disabled the error handling.

Also notice that when we use try!, we don't need to use the do-catch statement.

Note: If we use try! and there is an error, our app will simply crash.


Causes of Error in Swift

An error can occur for many reasons. Some of them are:

  • Invalid user input
  • Device failure
  • Loss of network connection
  • Physical limitations (out of disk memory)
  • Code errors
  • Opening an unavailable file

Since the errors abnormally terminate the execution of a program, it is important to handle these kinds of errors.

Did you find this article helpful?