Hello!
I'm curious about the best ways to handle errors that occur in asynchronous callbacks in Swift 2. It seems that returning an NSError (or ErrorType) via a callback argument is still a workable option, but this does not jive well with the new try/throw/catch/ErrorType syntax.
What is the correct way to throw an asyncronous error with the new syntax?
Here's a complete example to demonstrate:
MyPlayground.playground
import Foundation
import XCPlayground
enum Either<L,R> { case Left(L); case Right(R) }
enum MyError : ErrorType { case Failure }
let succeed = arc4random_uniform(2) > 0
func performWorkSync_happy() throws -> String {
// This is great!
print("Sync start")
if !succeed {
throw MyError.Failure
}
return "Hello, World!"
}
func performWorkAsync_sad(callback : Either<String, MyError> / throws */ -> Void) -> Void {
print("Async start")
dispatch_async(dispatch_get_main_queue()) { () -> Void in
// TODO: This isn't quite right....
/*
if !succeed {
throw Example.Failed
} else {
return "Hello, World!"
}
*/
// TODO: This is not ideal, but it works
do {
try ({ if !succeed { throw MyError.Failure } } as () throws -> Void)()
callback(.Left("Hello, World!"))
} catch {
callback(.Right(error as! MyError))
}
}
}
// MARK: Usage
do {
let result = try performWorkSync_happy()
print("Sync result: \(result)")
} catch {
print("Sync error: \(error)")
}
performWorkAsync_sad { result in
switch result {
case let .Left(result):
print("Async result: \(result)")
case let .Right(error):
print("Async error: \(error)")
}
XCPSetExecutionShouldContinueIndefinitely(false)
}
XCPSetExecutionShouldContinueIndefinitely(true)
Thanks!