You could make a file that looks like this:
class ErrorHolder {
private var error: ErrorType? = nil
}
func trySomething(@noescape closure: (ErrorHolder) -> ()) throws {
let errorHolder = ErrorHolder()
closure(errorHolder)
if let error = errorHolder.error {
throw error
}
}
func trySomethingInClosure(errorHolder: ErrorHolder, @noescape closure: () throws -> ()) {
do {
try closure()
} catch {
errorHolder.error = error
}
}
Then, whenever you have a function like this:
func doSomething(@noescape closure: () -> ()) {
closure()
}
and you want to try to call it like this, but can't, due to the compiler error:
do {
doSomething { // error: invalid conversion from throwing function of type '() throws -> _' to non-throwing function type '@noescape () -> ()'
throw NSError(domain: "Foo", code: 1, userInfo: nil)
}
} catch {
print("Something went wrong: \(error)")
}
You can just invoke the trySomething functions like so:
do {
try trySomething { errorHolder in
doSomething {
trySomethingInClosure(errorHolder) {
throw NSError(domain: "Foo", code: 1, userInfo: nil)
}
}
}
} catch {
print("Something went wrong: \(error)")
}
and get the output:
Something went wrong: Error Domain=Foo Code=1 "The operation couldn’t be completed. (Foo error 1.)"
It introduces a little pyramid-of-doom-ness into the code, but it will work to let you propagate errors out of a closure. Of course, this won't work with async code.