Error Handling in Swift 2.0
One of the features in Swift 2.0 announced at WWDC 2015 is the new model of error handling.
Finally, we can do that in nice, readable way without using pointers to NSError like it was in Objective-C.
How to achieve that?
First of all, we have to create an Enumeration with errors we could get, and one of the important things is that enum has to conform to a new protocol called ErrorType
.
It is worth to add that new error handling model was designed to work with NSError
which also conforms to a new protocol, so this code works also in a case of using Objective-C and Swift in one project.
I decided to show you how it works, based on a real life example…
1 2 3 4 5 | enum BreakfastErrors: ErrorType { case emptyFridge case noMilk case noEggs } |
The next step here is to write a function which can throw one (or more!) of our errors.
1 2 3 4 5 6 7 8 9 | func scrambledEggs(fridge: Fridge) throws -> String { guard !fridge.empty else { throw BreakfastErrors.emptyFridge } if !fridge.eggs { throw BreakfastErrors.noEggs } else { return "Cool, let's cook it" } } |
As you can see an implementation of that is really easy. Well, we have three new keywords used here but don’t worry, I will explain them right now.
By using throws
we have announced that our function can throw errors
guard
let us quickly check if one of the most important conditions is fulfilled and if not we don’t have to go deeper into the function
throw
just „return” one of the errors.
Ok, how we can use it now then? Just like that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | let fridge = Fridge(milk: false, eggs: true) do { var resultsOfCooking = try scrambledEggs(fridge) print(resultsOfCooking) } catch BreakfastErrors.emptyFridge { print("fill the fridge") } catch BreakfastErrors.noEggs { print("go and buy some eggs!") } catch BreakfastErrors.noMilk { print("go and buy some milk!") } catch { print("something else..") } |
So to test our throwing function we have use do-catch block. Each function which can throw has to be preceded by try
.
In a catch block, we’re handling not only possible errors about which we know but all of them. That’s why we had to add one more “universal” catch at the end.
Note that new error handling model have to be exhaustive.
Below one more example how we can create catch block in a bit different way, but still by fulfilling all cases:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | do { try pancakes(fridge) } catch let error as BreakfastErrors { switch error { case .emptyFridge: print("fill the fridge") case .noEggs: print("go and buy some eggs") case .noMilk: print("go and buy some milk") } } catch { print("something else") } |
If you don’t want to use catch block because you’re sure error will not happen, you can use try!
to force call without catching the errors.
1 2 | //I'm sure eggs are in the fridge let breakfast = try! scrambledEggs(fridge) |
By using this way of dealing with errors in Swift 2.0, you can for an example easily validate text fields in your app, or inform the user about not fulfilled conditions (like too short password, or usage of not allowed characters in the last name). Of course, you can use it also for working with REST API, or file management.
If you are not using it yet, I’m sure there are places in your application where you can apply it to improve your code quality.
As you can see new Error Handling model in Swift 2.0 is really easy to implement. Improve the readability and provide a clean way to inform your user or analytics tool, something went wrong.
You can find complete source code on Droids on Roids’s GitHub repository.
Ready to take your business to the next level with a digital product?
We'll be with you every step of the way, from idea to launch and beyond!