With the new Xcode 7 beta 6 that was released earlier this week, Apple introduced the new try? keyword. It gives us some more flexibility when handling operations that may throw errors.
Previusly, if you weren’t interested in the error, you still had to catch it.
func doSomething() { do { let data = try loadFile() // Do something with the data } catch { } }
You didn’t have to do anything in the catch block, but it made the intent of the code less clear. Did the developer forget to finish this implementation or was it intentional?
The only other option was to use try! which let you omit the catching but crashed if it threw. Therefore try! should only be used if you are certain that it won’t throw an error.
func doSomething() { let data = try! loadFile() // This better not throw! // Do something with the data }
This would be fine if you are loading a file from your own bundle that you know exists. You should always be careful when using try! .
Have you tried to try?
The new try? keyword lets us call operations that might throw and if it succeeds it will wrap up the results in an optional. If it fails however, then it will just be nil . It is particularly useful together with the if let statement and the new guard statement introduced in Swift 2.0.
func doSomething() { if let data = try? loadJsonFile() { // Do something with data } }
In this case we are not interested in any error that might get thrown, only if it works or not.
func doSomething() { guard let data = try? loadFile() else { return } // Do something with the data }
This code does essentially the same thing as the previous example but uses the guard statement instead. What these two examples show, boils down to a little bit cleaner code while maintaining safety.
If you haven’t tried guard yet, I recommend reading this article that explains it well: http://ericcerney.com/swift-guard-statement/
Keep in mind
try? statements always adds an extra layer of optionals. This means that if the return type of an operation that might throw is String? , the resulting type of calling that method with try? will be String?? or Optional<Optional<String>>
func doSomething() { guard let data = try? loadFile() else { return } // The operation didn't throw, but data is still an optional: (NSData?) if let unwrappedData = data { // Do something with the unwrappedData } }
The code above could be compressed down to even more readable code by chaining the expressions in the guard statement like this:
func doSomething() { guard let data = try? loadFile(), let unwrappedData = data else { // Either it threw or it returned nil return } // The operation didn't throw and unwrappedData is ready for use }
That’s about it, there’s not much more to it. This will definitely let me write cleaner code. I hope it will be of great use to you too!