Swift Do Catch
Do catch is a block that runs throwing code and sends each error to a matching catch block. The catch blocks are tried in order until one matches the error.
A catch for one case
The first catch names the emptyName case, so it prints its own line for the empty name. The plain catch after it stays unused here.
enum OrderError: Error {
case emptyName
case insufficientFunds(coinsNeeded: Int)
}
func order(name: String, paid: Int) throws -> String {
if name.isEmpty {
throw OrderError.emptyName
}
if paid < 10 {
throw OrderError.insufficientFunds(coinsNeeded: 10 - paid)
}
return "Order placed"
}
do {
let result = try order(name: "", paid: 20)
print(result)
} catch OrderError.emptyName {
print("Name is empty")
} catch {
print("Order failed")
}Binding the carried number
Paying 6 toward a price of 10 throws the insufficientFunds case carrying 4. The catch binds that number and prints how many more coins are needed.
enum OrderError: Error {
case emptyName
case insufficientFunds(coinsNeeded: Int)
}
func order(name: String, paid: Int) throws -> String {
if name.isEmpty {
throw OrderError.emptyName
}
if paid < 10 {
throw OrderError.insufficientFunds(coinsNeeded: 10 - paid)
}
return "Order placed"
}
do {
let result = try order(name: "Ana", paid: 6)
print(result)
} catch OrderError.insufficientFunds(coinsNeeded: let needed) {
print("Need \(needed) more coins")
} catch {
print("Order failed")
}A plain catch prints the error
This do block has only a plain catch, and it prints the error itself. The print shows the case name emptyName.
enum OrderError: Error {
case emptyName
case insufficientFunds(coinsNeeded: Int)
}
func order(name: String, paid: Int) throws -> String {
if name.isEmpty {
throw OrderError.emptyName
}
if paid < 10 {
throw OrderError.insufficientFunds(coinsNeeded: 10 - paid)
}
return "Order placed"
}
do {
let result = try order(name: "", paid: 20)
print(result)
} catch {
print(error)
}try? gives an optional
The try? call that succeeds holds its text inside an optional, and if let opens it for the print. The failing try? call holds nil, and the test proves it.
enum OrderError: Error {
case emptyName
case insufficientFunds(coinsNeeded: Int)
}
func order(name: String, paid: Int) throws -> String {
if name.isEmpty {
throw OrderError.emptyName
}
if paid < 10 {
throw OrderError.insufficientFunds(coinsNeeded: 10 - paid)
}
return "Order placed"
}
let good = try? order(name: "Ana", paid: 20)
if let text = good {
print(text)
}
let bad = try? order(name: "", paid: 20)
print(bad == nil)Example
enum OrderError: Error {
case emptyName
case insufficientFunds(coinsNeeded: Int)
}
func order(name: String, paid: Int) throws -> String {
if name.isEmpty {
throw OrderError.emptyName
}
if paid < 10 {
throw OrderError.insufficientFunds(coinsNeeded: 10 - paid)
}
return "Order placed for \(name)"
}
do {
let result = try order(name: "Ana", paid: 12)
print(result)
} catch {
print("Order failed")
}
do {
let result = try order(name: "Bo", paid: 6)
print(result)
} catch OrderError.insufficientFunds(coinsNeeded: let needed) {
print("Need \(needed) more coins")
} catch {
print("Order failed")
}
do {
let result = try order(name: "", paid: 20)
print(result)
} catch OrderError.emptyName {
print("Name is empty")
} catch {
print("Order failed")
}Key points
- Do catch runs throwing code and sends each error to a matching catch block.
- A catch written with one error case runs only for that case.
- A catch can bind the associated value of a case to a name it can use.
- A plain catch with no case written matches any error.
- A plain catch can print the error itself, and the print shows the case name.
- The try? form turns a throwing call into an optional, holding the value on success and nil on failure.
In this example, the order function throws emptyName for an empty name and insufficientFunds with the missing amount when the payment is under 10. The first do block orders for Ana with 12 paid and prints the placed line. The second do block pays 6 for Bo, and its binding catch prints that 4 more coins are needed. The third do block passes an empty name, and its specific catch prints Name is empty.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท Programiz Swift Compiler
Exercise
An order costs 10 coins and a buyer pays 6, so the error carries coinsNeeded 4. What can a catch block print by binding that value?