09. How to use rethrows in Swift?

It will take about 5 minutes to finish reading this article.

In Swift, both the rethrows keyword and the throws keyword are used to modify functions and exception handling.

The difference, however, is that rethrows indicates that this function does not actively throw errors under normal circumstances, but that it accepts one or more closures that throw errors as arguments, and may then continue to pass those errors on to the caller.

It can be simply understood that throws allow possible exceptions to be handled by the function or method (e.g., with do-catch), whereas rethrows just passes the throws; the function itself doesn’t need to handle the exception.

The use of the rethrows keyword is often used for functions that take closure arguments that may throw errors. The following is a simple example of code that uses the rethrows keyword:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
enum MathError: Error {
case divisionByZero
}

func safeDivide(_ numerator: Int, by denominator: Int) throws -> Int {
guard denominator != 0 else {
throw MathError.divisionByZero
}
return numerator / denominator
}

func processNumbers(_ a: Int, _ b: Int, using closure: (Int, Int) throws -> Int) rethrows -> Int {
let result = try closure(a, b)
return result
}

func printResult(_ result: Int) {
print("Result:", result)
}

The calling code is as follows:

1
2
3
4
5
6
7
8
9
let a = 10
let b = 5

do {
let divisionResult = try processNumbers(a, b, using: safeDivide)
printResult(divisionResult)
} catch {
print("Error:", error)
}

In this example, we define a safeDivide(::) function to perform division of an integer, which will check if the denominator is zero. Then we define a processNumbers(_:using:) function that takes a closure argument to process two integers. This function is labeled rethrows because it does not actively throw errors, but may pass them on to the caller.