Swift Tutorial · Closures, Generics and Errors · Lesson 21 of 30

Swift Error Handling

Throw, propagate and catch errors with throws, try, do-catch, typed throws, try? and Result.

Create a free account to save this page, take notes and track your progress. Sign in

throws, try and do-catch

A function that can fail is marked throws; every call to it is marked try, so failure points are visible. Errors are usually enums conforming to Error. do/catch handles them, and catch clauses can match specific cases.

throws, try and do-catch
enum CheckoutError: Error {
    case emptyCart
    case outOfStock(item: String)
}

func checkout(_ cart: [String], stock: [String: Int]) throws -> String {
    guard !cart.isEmpty else { throw CheckoutError.emptyCart }
    for item in cart where stock[item, default: 0] == 0 {
        throw CheckoutError.outOfStock(item: item)
    }
    return "ordered \(cart.count) items"
}

let stock = ["mug": 3, "teapot": 0]
for cart in [["mug"], [], ["mug", "teapot"]] {
    do {
        print(try checkout(cart, stock: stock))
    } catch CheckoutError.outOfStock(let item) {
        print("sorry, \(item) is out of stock")
    } catch {
        print("failed: \(error)")
    }
}

Output

ordered 1 items
failed: emptyCart
sorry, teapot is out of stock

Run this on your computer — see “Get Started” for setup.

try?, typed throws and Result

  • try? turns an error into nil.
  • Typed throws (Swift 6): throws(CheckoutError) declares exactly which error type a function throws.
  • Result<Success, Failure> stores a success or failure as a value, for example to pass it around.
Typed throws, try? and Result
enum ParseError: Error { case notANumber(String), negative(Int) }

func parseQuantity(_ text: String) throws(ParseError) -> Int {
    guard let n = Int(text) else { throw .notANumber(text) }
    guard n >= 0 else { throw .negative(n) }
    return n
}

do {
    _ = try parseQuantity("-2")
} catch {
    print("caught \(error)")          // error is ParseError here, not any Error
}

print(try? parseQuantity("7") as Any)
print((try? parseQuantity("x")) ?? 0)

let result = Result { try parseQuantity("12") }
switch result {
case .success(let n): print("parsed", n)
case .failure(let e): print("error", e)
}

Output

caught negative(-2)
Optional(7)
0
parsed 12

Run this on your computer — see “Get Started” for setup.

Test yourself

What does try? do with an error?

  1. Crashes the program
  2. Converts it to nil
  3. Prints it
  4. Rethrows it
Show answer

Answer: Converts it to nil

Was this page helpful?