What are the differences between throws and rethrows in Swift?
From "Declarations" in the Swift book:
Rethrowing Functions and Methods
A function or method can be declared with the
rethrows
keyword to
indicate that it throws an error only if one of it’s 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.
A typical example is the map
method:
public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]
If map
is called with a non-throwing transform, it does not throw
an error itself and can be called without try
:
// Example 1:
let a = [1, 2, 3]
func f1(n: Int) -> Int {
return n * n
}
let a1 = a.map(f1)
But if map
is called with a throwing closure then itself can throw
and must be called with try
:
// Example 2:
let a = [1, 2, 3]
enum CustomError: Error {
case illegalArgument
}
func f2(n: Int) throws -> Int {
guard n >= 0 else {
throw CustomError.illegalArgument
}
return n*n
}
do {
let a2 = try a.map(f2)
} catch {
// ...
}
- If
map
were declared asthrows
instead ofrethrows
then you would
have to call it withtry
even in example 1,
which is "inconvenient" and bloats the code unnecessary. - If
map
were declared withoutthrows/rethrows
then you could not
call it with a throwing closure as in example 2.
The same is true for other methods from the Swift Standard Library
which take function parameters: filter()
, index(where:)
, forEach()
and many many more.
In your case,
func throwCustomError(function:(String) throws -> ()) throws
denotes a function which can throw an error, even if called with
a non-throwing argument, whereas
func rethrowCustomError(function:(String) throws -> ()) rethrows
denotes a function which throws an error only if called with a
throwing argument.
Roughly speaking, rethrows
is for functions which do not throw
errors "on their own", but only "forward" errors from their function
parameters.
How to declare a rethrowing function?
Remember, the argument is of type () -> Int
! So you need to call the function passed in to get the result! You also need try
since the function can throw.
func handleResult(_ index: (() throws -> Int)) rethrows {
print(try index() * 2) // see the "()"?
}
Now you can use it like this:
let myArray = [true]
try handleResult(myArray.indexOfFirstTrue)
rethrows for class/struct instance method in swift error handling
As said here: https://stackoverflow.com/a/33350601/1370336, in your "MiddleParser" struct, you don't have to wrap the call in a do
- catch
block (since your function is marked with throws
), just use:
inners.append(try self.innerParser.parse(innerJson))
Throw from a trailing closure in Swift
func innerClosure(a: String, completion: (String) throws ->Void) {
try? completion(a + ", World")
}
does not throw an error because try?
is an “optional try”: It returns an Optional
which is nil
in the case of an error. Here the return value is ignored, so that errors are ignored silently.
What you want is
func innerClosure(a: String, completion: (String) throws ->Void) rethrows {
try completion(a + ", World")
}
which makes innerClosure()
a throwing function only if called with a throwing parameter.
func iCanThrow()
can also be marked as rethrows
instead of throws
because it does not throw an error “on its own.”
See also What are the differences between throws and rethrows in Swift?.
Save rethrowing function as a non-throwing closure
Until someone comes up with a better solution: Use a wrapper
func f(_ c: () throws -> Void) rethrows { try c() }
let x: (() -> Void) -> Void = { f($0) }
Generic requirement that Some: AsyncSequence is not throwing
When this proposal is fully implemented you will be able to express conformance to a failable sequence by providing some syntax sugar
extension AsyncSequence where nothrow AsyncIterator {
or
struct Foo<S: nothrow AsyncSequence>
This comes from the @rethrows
annotation currently attached to AsyncSequence
@rethrows public protocol AsyncSequence
swift syntax. What is R in withUnsafeMutableBytes R (_...
withUnsafeMutableBytes<R>(_: (UnsafeMutableRawBufferPointer) throws -> R) rethrows -> R
means that:
- Function
withUnsafeMutableBytes
takes a function/closure (that maythrow
error) fromUnsafeMutableRawBufferPointer
to some generic typeR
. WhatR
depends on the caller. - Function
withUnsafeMutableBytes
returns value of the same generic typeR
taken function returns. And it mayrethrow
error, if it was thrown by the closure.
So basically generic parameter R
here is just a way to say that return types of withUnsafeMutableBytes
and the closure
it takes will be identical, and it's not hardcoded.
Related Topics
Swiftui: Pop to Root View When Selected Tab Is Tapped Again
How to Use an Nsattributedstring with a Scrollview in Swiftui
How to Create a Fixed-Size Array of Objects
Programmatically Navigate to New View in Swiftui
Convert Avaudiopcmbuffer to Nsdata and Back
Swift Dictionary Default Value
Swiftui iOS 14 Widget Countdown
How to Set the Legacy Swift Versions for Each Pod in Podfile
How to Convert Range in Nsrange
Extension May Not Contain Stored Property But Why Is Static Allowed
How to Loop Through View Outlets in a Uiviewcontroller with Swift
How to Make Class Methods/Properties in Swift
How to Check If Time Is Within a Specific Range in Swift
How to Left Align the Title of a Navigation Bar in Xcode
Stop a Dispatchqueue That Is Running on the Main Thread
How to Change Back Button Title on Navigation Controller in Swift3