Keep your Swift Exceptions clean, easy to update and future proof
Finally a descent exception model in a modern language, a model where it’s absolutely obvious when to use do/try/catch. If you miss it, the compiler (precompiler/static analyzer) will tell you. There is no, or very little overhead in using Exceptions in Swift, unlike Java and C# where the runtime must create the exception and unwind the stack and then throw.
In swift, by marking the function as throws, its signature is actually altered and its returning a generic enum Either<T1, T2>, where T1 is the successful result and T2 is the thrown error type, but all this is hidden for you.
Another great feature (probably discussable) is that you don’t need to provide a list of all the exceptions that can be thrown by a function, like in Java.
- In Swift you can’t call functions that throws without knowing (you must call it with try or try!)
- There is no significant overhead using and throwing exceptions in Swift.
So how do I keep my code clean using Exceptions in Swift?
So there you are, your boss told you to work on that new login code for the company’s most popular app. Your new target for the update is Swift 2 and you want to use Exceptions. You start by defining a simple Error/Exception for you login. If the user tries to login with an empty username or an empty password you want to show some feedback so you define a new error type (Adopting to ErrorType protocol).
Now when you have your error type defined you start working on a simple login method which takes username and password as parameters. If the optional cant be unwrapped or its empty then you throws a proper exception.
The method is marked with the new keyword “throws” and it returns a string, a token that will be used by some other method. The only thing left is to use it in your new code.
You are now catching all possible login errors that you defined. But somehow this code is getting cluttered. It would be even more cluttered if you want to handle more exceptions, like “user not found”, or “invalid username” or “invalid password”. A much better solution would be to write an extension to our LoginError enum.
We are adopting to CustomStringConvertable protocol, which gives us the possiblity to implement description of self. We can below refactor our previous version of Login().
It’s now easier and more convenient to add more Exception cases for our login code. We only need to throw them and add them to the extension. This is in my opinion a good approach to keep your exceptions clean.
Follow me on Twitter: https://twitter.com/konrad1977