Swift 2’s try?
operator bridges optionals and error handling by converting thrown errors into nil results. With it, you can use guard statements and conditional binding to focus development solely on success cases.
guard let foo = try? somethingThatMayThrow else { handle error condition without specific details and leave scope}
You lose any returned error information with this approach. The tl;dr version of the rest of this post is this: Discarding error information is kind of sucky. Why not automagically build in context and error printing with alternatives to try? and try!.
A while back, I shared a basic way to emulate try?
without discarding those errors entirely. The following implementation first prints returned errors and then continues to return the result/nil return type that try?
normally gets you:
func attempt<T>(block: () throws -> T) -> Optional<T>{ do { return try block() } catch { print(error); return nil } }
This works great when returned values play some further role but what do you do when you want to use guard statements with failable procedures that don’t return meaningful values, while retaining attempt
‘s error-printing behavior. For example, consider many of NSFileManager’s file creation and deletion utilities.
NSFileManager.defaultManager().removeItemAtURL(someURL)
Your choices are this: wrap in a do-catch
block (wordy), use attempt
with try?
and then try to wrangle the returned nil value, or use try!
and lose all the error information.
There’s of course, another way. In the gist you find at the end of this post, I’ve built attemptFailable
. It wraps throwing statements in minimal printing guard/try system that returns Boolean values. Here’s how that looks in use:
if NSFileManager.defaultManager().fileExistsAtPath(myPath) { guard (attemptFailable{try NSFileManager.defaultManager() .removeItemAtURL(myURL)}) else {abort()} }
Not ideal, obviously, but pretty handy when writing utilities in playgrounds, which I do more and more these days. (Playgrounds are awesome. Buy my book.)
You can enhance try!
in a similar fashion. The doOrDie
function in this gist creates more informative versions for try-and-die than the Swift-supplied option. Like attempt
and attemptFailable
, it captures context and thrown errors and print both before continuing with standard try!
execution termination.
Here’s the code.
2 Comments
Error handling was already not pretty sexy with the boring do-try-catch syntax and the missing error type, so giving us try? to avoid it completely won’t help make it more attractive!
I don’t get the Swift team on that move.
[…] Sadun, 原文链接 […]