Some codes and contents are sourced from Apple’s official documentation. This post is for personal notes where I summarize the original contents to grasp the key concepts
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/declarations/#Rethrowing-Functions-and-Methods
What is rethrows in Swift?
A function or method can be declared with the
Applerethrowskeyword to indicate that it throws an error only if one of its function parameters throws an error. These functions and methods are known as rethrowing functions and rethrowing methods. Rethrowing functions and methods must have at least one throwing function parameter.

Let’s check Foundation’s map function. A transform is a rethrowing function parameter.
It means transform function can throwing an error.
A rethrowing function or method can contain a
throwstatement only inside acatchclause. This lets you call the throwing function inside ado–catchstatement and handle errors in thecatchclause by throwing a different error. In addition, thecatchclause must handle only errors thrown by one of the rethrowing function’s throwing parameters. For example, the following is invalid because thecatchclause would handle the error thrown byalwaysThrows().A throwing method can’t override a rethrowing method, and a throwing method can’t satisfy a protocol requirement for a rethrowing method. That said, a rethrowing method can override a throwing method, and a rethrowing method can satisfy a protocol requirement for a throwing method.
Apple

alwaysThrows function is not a function parameter. In a someFunction, only callback function parameter can throwing a error.
enum SomeError: Error {
case error
}
enum AnotherError: Error {
case error
}
func alwaysThrows() throws {
throw SomeError.error
}
Example 1. This one it working fine.
func someFunction(callback: () throws -> Void) rethrows {
do {
try callback()
} catch {
throw AnotherError.error
}
}
Example 2. This one also working fine
func someFunction(callback: () throws -> Void) rethrows {
try callback()
}
Example 3. This one compile error (A function declared ‘rethrows’ may only throw if its parameter does)
func someFunction(callback: () throws -> Void) rethrows {
do {
try alwaysThrows()
} catch {
throw AnotherError.error
}
}
Because alwaysThrows function is not a part of someFunction’s parameter.
Example 4. Use try in a closure

When you use try in a closure, You should marked try someFunction
try someFunction {
let decoder = JSONDecoder()
try decoder.decode(String.self, from: Data())
print("someFunction")
}
Example 5. Call a closure without using try

If you don’t use try in a closure, It’s okay not marking try at someFuntion.
If I change rethrows to throws in the example above, what happens?

There is a compile error. Always use try keyword when you call a someFunction.

Let’s make a customMap using rethrows keyword.

Built-In map function uses rethrows keyword.

var input = [1, 2, 3, 4, 5]
extension Array {
func customMap<T>(_ transform: ((Element) throws -> T)) rethrows -> [T] {
var result = [T]()
for item in self {
let transformedValue = try transform(item)
result.append(transformedValue)
}
return result
}
}
let output = input.customMap { item in
"\(item)"
}
let output2 = input.map { item in
"\(item)"
}
map itself uses try keyword. Because It allows users to use try in a closure. It we are not using try keyword in a closure we can simply use it without try keyword.

Leave a comment