Swift Programming – Error Handling

In this tutorial you’ll learn about error handling in Swift. To follow along, it is recommended to have a Mac and the Xcode IDE installed on it. This tutorial makes use of the Xcode playground for compilation of the Swift codes. If you do not have a Mac, you may try using the open-source code editors which support different operating systems such as AtomSublimeText or VSCode.

Error Handling

You can use error handling to better respond to failures that might occur in your codes. Swift supports throwing, catching, propagating and manipulating recoverable errors at runtime.

Representing and Throwing Errors

Swift provides an Error protocol for types of error values to be conformed to. You can use an enumeration conforming to the Error protocol for a group of related errors. Let’s say you want to withdraw money from your bank account, you can define an enumeration with related errors which may occur.

enum BankingError: Error {
    case invalidPin
    case insufficientFund
    case expiredCard
    case depositFundRequired(amount: Int)

You can handle unexpected cases and stop execution of codes by throwing an error. The keyword throw is used for throwing an error.

throw BankingError.depositFundRequired(amount: 1000)

Handling Errors

You must surround codes to execute for handling the error when an error is thrown. These codes could be for correcting the issue, finding some alternative ways or informing the user. There are four ways for handling an error:

  • propagate the error from a function to the code that calls that function.
  • use a docatch statement to handle the error.
  • handle the error as an optional value.
  • assert that the error will not occur.
class BankAccount {
    var balance = 0.0
    // propagating an error from a function
    func deposit(amount: Double) throws -> Double {
        if amount <= 0.0 {
            throw BankingError.depositFundRequired
        balance += amount
        return balance
    // propagating an error from a function
    func withdraw(amount: Double) throws -> Double {
        if balance < amount {
            let difference = amount - balance
            throw BankingError.insufficientFund(amount: difference)
        balance -= amount
        return balance

let bankAccount = BankAccount()

// using a do-catch statement to handle an error
do {
    try bankAccount.deposit(amount: 0.0)
} catch BankingError.depositFundRequired {
    print("Deposit fund is required")
} catch BankingError.expiredCard {
    print("Expired card detected")
} catch BankingError.insufficientFund(let amount) {
    print("Insufficient fund. Amount required is \(amount)")
} catch BankingError.invalidPin {
   print("Invalid pin")

// handling an error as an optional value
let currentBalance = try? bankAccount.deposit(amount: 10000)
print("Balance is now \(currentBalance ?? 0.0)")

// asserting that the error will not occur
let netBalance = try! bankAccount.withdraw(amount: 100)
print("Balance is now \(netBalance)")