Giving up on Alamofire
You’ve probably asked yourself those questions a dozen times for you app. Should I use a library for this feature? Is this one still maintained? What if it’s not updated on the next Swift version?
On the one hand, you will save a lot of time and not reinvent the wheel, also you feel a bit lazy right now, and those people know what they’re doing right? And on the other, well, if you code it yourself, you can make something faster and better because it only meets your requirements, and if it needs an update, then it won’t take you long because you’ll know everything that there is to know about your code.
My name is Emilien, I’m the lead iOS engineer at Her, the lesbian dating app. App in which we use way too much external libraries. I’ve never been a big fan of them, because you rely too much on people and when comes a time where you have a problem or when there is an update to do; well, there’s really just you. It becomes a lot of pain to fix, to switch for another one, or recode everything yourself.
Alamofire is a great library. When you start in Swift, you don’t have to worry about the complicated part of managing your requests. You simply add the library to your project and that’s it, everything is handled for you (well pretty much). The community around it is is also awesome, there are so many projects that make the best out of it. And since they’re great, why not also add them to your project? But wait, what happen when you have a problem with Alamofire?
The not-so-great part about Alamofire
The big problem with Alamofire is that you become way too dependent on it, all your interface with your API depends on it; and if you’re kind of new to iOS development you are likely to make calls to Alamofire pretty much everywhere. Just like this:
Alamofire has also a paradoxical problem. It has been made by really smart people. The code is really clean, but when it comes to understanding how it works it is quite painful. It doesn’t do anything really complicated in theory, but the way the code is made with many layers of abstractions makes it quite difficult to understand at a first glance.
At Her, we had a few issues. The first one wasn’t so bad, Alamofire updated its User-Agent header signature without telling anyone. It took us a few hours to understand what was going on, another hour to find where that header is set in the library, and another one to update our regex accordingly. (Arg dammit, how do I do a regex again?)
But more dramatically, with the release of Swift 3, Alamofire decided to not support iOS 8 anymore. Our options were to abandon iOS 8 as well, or to abandon Alamofire. We are currently in the process of monetizing the app, so losing 5–7% of our users is simply not an option.
Don’t rely too much on external libraries
At Her, and like many other apps, we relied heavily on Alamofire, and that’s really bad. Abandoning an OS version should be your decision and your decision only, not the one of some external library.
It’s not that we don’t believe in external libraries, it can actually make sense for a lot different reasons, but be really careful with it. You can check this great article about dependencies:
So yes, sometimes it make sense to integrate external code. It can be that, what you’re trying to achieve is quite complicated like generating QR codes. It would take many days to understand how QR Codes are made and some libraries have been doing this for ages and it has worked pretty well from day one. It can also be because it’s a simple but tedious task with a well defined mechanic, like using the Keychain.
But the weird thing is, it’s actually not complicated at all to perform a simple HTTP request, and it’s not tedious neither. Here’s what a login request would look like:
Yes, that’s it. Your requests are almost never more complicated than that.
So what about when they are actually more complicated than that? That’s when you think about using a library, you probably don’t want to handle the multipart yourself or the file upload in the background.
Well, it is actually not much harder. Sure, it might take a couple of more hours to implement, but in the end, you’ll know how multipart actually works, which is kind of nice, and trust me those couple of hours is more of an investment because you’ll lose more time figuring why sometimes the magic behind Alamofire doesn’t work.
So this was our situation at Her, we needed to implement something new for our networking layer, the only part that was a bit more difficult was the multipart upload that we use for image upload. Nothing really extraordinary.
But isn’t the case of most people? What if we could build a library that is really simple. Library might not be the right term, we don’t want a black box that does magic. We want something that anybody can understand and adapt to their needs.
A new networking library
We wanted something simple and modular. We also wanted to provide a structure to make your life easier when dealing with APIs. In your app you certainly manage one and sometimes even many different APIs. In our case we use Giphy and Google Maps as well. In the future we could use Spotify or Deezer.
Those APIs have a behavior. In some of them you would like to send your token as a parameter in every request, in others you would need to pass it as a header. The way they handle errors could be very different as well. Some APIs might return you an appropriate HTTP code. Some might return a HTTP code 200 with an error message, some might also send you a 404 to obfuscate what is behind.
So we wanted to build something that could map that behavior for each one of those.
Alamofire doesn’t provide any structure for managing different APIs; and even if you have only one, you have to manage everything by yourself if you want to deal with custom headers or errors. Moya is a great framework that will give you this kind of structure and works on top of Alamofire, but it is not really concise and if you have a lot of different endpoints, its `switch` statements become quite messy. So we believed we could do something better and simpler, something that integrate the best of both framework and something that is really easy to understand in case something goes wrong at some point.
Our framework is called Nikka, we’ll let you discover it by yourself in this next article and hope you’ll like it as much as we do: