Home » How To » How to implement network requests to a REST API in Swift 3 with Alamofire 4

How to implement network requests to a REST API in Swift 3 with Alamofire 4

To perform a request we use:

  • NetworkRequestController
  • Router enum RouterName:URLRequestConvertible
  • Method that performs the request and handles the response

NetworkRequestController

We have one NetworkRequestController class. This controller handles all the requests. This is the only controller that actually ‘connects’ to the internet and retrieves data. This way, if — in our case — Alamofire changes their API, we only have to change one class (or two methods, really). Or if we add another statuscode/expected response, we only have to revise or add a few lines of code.

To be able to create a model easily, we use the recommended JSON Serialization of Alamofire. They have lots of examples within their documentation.

The modification we made to the serialization protocols is to return our optional custom NetworkError. That addition looks like: if let error = NetworkStatusCode(rawValue: response.statusCode)?.networkError { return .failure(error) } (more about this at Error Handeling).

The NetworkRequestController methods actually connect to the API. One method expects an array of JSON objects, another expects a singular JSON object. The declaration of the methods looks like this:

Declaration request method

The implementation of the methods looks like this:

Implementation request method

The first method explained:

1The performed request expects a generic type T, that conforms to the ResponseObjectSerializable protocol. The method requires a networkRequest:URLRequestConvertible. More about requests later at Routers.

2Call Alamofire with the request.

3 Call the responseHandler with the optional model (<T>) in the value or response error.

Error Handling

We always agree on statuscodes prior to starting a new project. In which case the app is able to show the appropriate error or handle the error. For example, when the request returns a 401 we often doif requestError == NetworkError.unauthorized { UserController.logout() }

Handle network request errors

Router

Personally, I think this is the best and most efficient part. We use Routers to define the API requests. A Router is a CRUD-based Enum that defines the options for a request like the HTTPMethod, parameters or headers.

A basic router to create a new User and look up logged in user looks like this:

The router is mostly self explanatory and I’ll show an example of how to use the UserRouter later on. I’ll explain most lines.

1 We import Alamofire to be able to use URLRequestConvertible and typealias Parameters.

4 and 5 are the two different possible request. We can use a UserRouter.create(params) to create a new user or UserRouter.get to request the logged in user.

7 The API endpoint, for example: www.mywebsite.com/api/user. Where the static URL (www.mywebsite.com/api/) is saved under Settings.apiURL (see 21)

13 the HTTPMethod.

20 creates an URLRequest and adds all the components together.

22 grab the static URL and append the path.

27 append the HTTPMethod

30 If it is part of the Router, append the Parameters JSON encoded.

36 Add the headers. All the Routers call the same addHeaders method, so we DRY up our code. When a user is logged in, we append the authentication code.

This Router file is an example of a few requests. It keeps our projects well organized and adding new routers is pain-free and can be done in minutes. It’s practically impossible to forget adding necessary components of your request. I save a code snippet in Xcode for a Router template.

Here’s a Real Example

We have a Router and a general request method, so we can make our first request. Let’s say we have a User who wants to sign-in. We grab the user details and create our request. The implementation of our UserController.login method could look like this:

Yes. That’s a one line request.

Source link