Alamofire API Manager
In my company, we usually avoid using third-party libraries. There are many reasons to do that. We like to learn new stuff and developing things ourselves is the best way of doing so. We don’t want a project to depend on other engineers and their responsiveness when swift gets a new update, or we find a bug. Sometimes we need just a few methods from a library, so we don’t want to add a whole framework.
However, that’s not always the case. There are a lot of good frameworks which we can use without worries and Alamofire is one of them.
The idea is to create a reusable and straightforward API manager. It will have to figure out which URL to use, what is the type of method, to configure header, to add params and to parse data and errors. However, before implementing the API manager, we will have to create some helper classes using a single responsibility principle.
ErrorObject
Error object is a class which we will use for parsing network errors. You’ll define the structure of the object with backend developers. In our case, the error object has only two variables. Key is the variable we use for localization of errors so we can show a message in proper language to the user. If we don’t have it localized, we use message variable.
EndpointType
EndpointType is a protocol which defines all values that we need to form URL request. When formed we will pass it to our API manager. Because HTTPMethod, HTTPHeaders, and ParameterEncoding are objects from Alamofire library, we need to import it.
EndpointItem
EndpointItem is an enum object which implements EndpointType protocol. For each request on a server side, we will add new value to EndpointItem.
We’ve chosen this implementation because it’s easy to use, change, and to add and remove values. You can define rules for versioning your API, define different HTTP headers, you can communicate with multiple servers using this implementation. Moreover, everything is in one document. So if you change something, for example in the header variable, it’s easy to see all places where change will take place.
NetworkEnvironment
NetworkEnvironment is another enum object which will define a set of environments on a server side.
APIManager
Finally, we are starting the implementation of our API manager. Also, we are going to implement it as a singleton.
Oh yeah. We won’t argue now if singletons are good or bad. It’s a whole different topic. Only thing I will say about it is that misuse of the singleton is bad, not pattern itself. However, if you insist that this is not a way to go, this approach will still work without it.
Why API manager should be singleton:
- You need only one instance in the whole project. Having multiple APIManagers won’t give you any performance benefits. However, having one is an optimal solution regarding memory.
- Other classes should use APIManager as dependency. You’ll use singleton shared instance only when injecting it to other objects or in composition root.
API manager will have static variable network environment which we use to form URL in EndointItemObject.
Our APIManager should create URL requests using EndpointItem object. Also, it needs to parse data. Parsing is an easy task when using Codable. So all structs and classes that represent data models should implement Decodable and Encodable protocols. Then we can do this.
We are using generic argument T where T is Codable. T will inform APIManager about what kind of data we are fetching and what kind of object we want the manager to return. T can be any object or, an array of objects, which implements Decodable and Encodable protocols. After setting T, if needed, we can add request parameters.
If the request is successful, we’ll get a predefined object. If not we will initialize the error object and display it using AlertMessage.
Here are examples of implemented call method, assuming we’ve defined classes User and UserExists and have an instance of APIManager.
This implementation has one problem. If the server responds with an empty object, the app will crash because you can’t decode it. Thus we need to implement one more method. Now the app won’t crash.
Conclusion
We have simple APIManager which is easy to use, upgrade or implement in another project. The only thing to change is the implementation of EndpointItem class. Also, remember because our APIManger is singleton you should inject it in a class when using it.
Thanks for reading :)
If this article was helpful and you want to hear more about similar topics, please clap, share, follow or comment.