Network Layer in Swift 4.0

Every time when i start a new project there is the same question. How to implement a network layer? To use external libraries like Moya, Alamofire etc. or to write it from the scratch.

My answer for this question is — Use pure Swift without any third-party libraries. It’s a super simple to implement protocol-oriented layer, type safe with enum to configure endpoints and fully testable, of course. In these few points you will learn how to write protocol oriented networking layer that you can customise.

First things first

Before you start, it’s important to understand URLSessionand its constituent classes. In general URLSession is responsible for sending and receivng HTTPRequests. For basic requests you can use sharedsession which has no configuration object. It’s not as customisable as sessions you create by yourself, but it serves good starting point if you have very limited requirements. For other kinds of sessions, you instantiate a URLSessionwith one of three kinds of configurations:

  1. .default - session behaves as a shared session, but allows more configuration and to obtain data incrementally with a delegate.
  2. .ephemeral - session is also similar to shared session, but don’t write caches, cookies, or credentials to disk.
  3. .background - session let you perform uploads and downloads of content in the background while your app isn't running.

URLSession returns data in two ways:

  1. completion handler
  2. calling methods on a delegate

Within a session you can create URLSessionTask to retrieve data from the server, upload photos or download files. Moreover you can also resume, suspend and cancel tasks. URLSessionTask gives opportunity to pause running task for example when user leaves app and resume it when returns. The URLSession provides three types of tasks:

  1. data - sends and receives data using Data objects. Data tasks are intended for short, often interactive requests to a server.
  2. upload - similar to data tasks, but in general used to upload files and support background uploads while the app isn’t running.
  3. download - retrieve data in the form of a file and support background downloads and uploads while the app isn’t running.

In this tutorial you will use only first type of URLSessionTask to send request and handle response form the server.

Ok after a short recap of what URLSession can do and now let's do some practice.

ServiceProtocol

First you have to divide network layer to a small services. Keeping all requests in one class/enum is difficult to maintain and might transform into a monster massive thing. ServiceProtocol will be helper to create URLRequest. ServiceProtocol contains constituent components such as baseURL, path, method, headers, task and parametersEncoding. Go ahead and create your first file of simple networking layer.

HTTPMethod is an enum responsible for setting HTTP method of requests. URLRequest has property .httpMethod to set method String type.

Task is an enum responsible for configuring parameters for a specific service. You can add as many cases as are applicable to your network layer requirements. For example upload(Data), download(parameters: Parameters) etc. Example has only two cases to send plain request or with parameters.

ParametersEncoding

ParametersEncoding is an enum responsible for setting encoding type. In this example you have to use the most popular: URL and JSON.

Voilà! First part of creating network layer is done. Keep your head up and keep going! Let’s move to the next part — How to implement constructor of URLRequest.

Request

Before you send first request to the API you have to create custom request from ServiceProtocol. As you probably noticed Service has all information to construct Request. To avoid creating new class you will create an extension to URLRequest and URLComponents.

First of all: create URLComponents file. This extension will merge baseURL with path and will add parameters to the url if parameters encoding is url. Paste this code to your file:

  1. To get full path of url you need to append path to base url..
  2. Using your new url, you initialise a URLComponents.
  3. If parameters encoding is “url” and request has parameters — create array of [URLQueryItem] for each parameter and set to the queryItems.

Next step is URLRequest. Create file and add the following implementation:

  1. First create urlComponents.
  2. Using your new urlComponents initialise a URLRequest.
  3. Set httpMethod of the request equal to that of our ServiceProtocol.
  4. Set headers.
  5. If parameters encoding is “json” and request has parameters — use JSONSerialization to covert dictionary with parameters to Data. You can add try catch closure to handle the exception.

Next part done! Congratulations!

NetworkResponse

When you get response from sent request, completion handler returns unreadable information. Optional data, response and error says nothing. You have to create enum to handle response from API and display clear message. Create two files NetworkResponse and NetworkError. There are two cases:

  1. .success - if success - returns Decodable model
  2. .error - if error - returns error of type NetworkError.

For blogpost example NetworkError has only two cases:

URLSession

You have almost finished network layer. Last thing which need to be implement is a provider to send requests. To do that create new file ProviderProtocol and add the following implementation:

ATTENTION!: T must conform to Decodable protocol.

If ProviderProtocol is done, now you can start implementing last class URLSessionProvider which is the heart of your network layer. To do that: create new file and copy following code:

  1. URLSessionProvider conforms to ProviderProtocol which has been created few lines earlier.
  2. This approach is necessary to test network layer. It’s essential because in easy way you can switch session with mock file and simulate responses from API without internet connection. With the next blogpost i will explain you how to test network layer. For now please create a new file URLSessionProtocol and copy following code:

Next you will create request function. This function is responsible for all the vital work in our network layer. Add this method to URLSessionProvider.

  1. Initialise request from service object.
  2. Create URLSessionDataTask to send and receive data from API. Data tasks are intended for short, often interactive requests to a server.
  3. Start task. Session will send request to the server and wait for the response.
  4. handleDataResponse completionHandler returns optional values and you actually don't know if request has finished with success or error. You need extra method to parse response data and error.
  1. First you have to check if an error has occurred. If your API return some information in error, add custom init to the NetworkError enum and parse it.
  2. In this scenario all requests return a json data so if response is empty function returns error
  3. HTTPURLResponse contains status code of sent request. In this example requests with status code between 200...299 have success status in other cases failure.
  4. Use JSONDecoder to decode response data and return expected object with type T.

That’s all! Your network layer is completed in pure Swift, no third party libraries. In next part you will find out how to create simple service and send first request.

Demo

In this demo you will use free API (https://jsonplaceholder.typicode.com) which allows to fetch posts, comments and users info. First of all create file PostService and copy following code:

PostService implements two cases: fetch all posts and comments for specific postId. For both cases you use “GET” method and “url” parameters encoding. Case “all” doesn’t require any special parameters so you can use plain request but for “comments” case you need to send request with parameters (key: “postId”, value: Int).

Finally you are ready to send your first request and use implemented provider! Open ViewController and add the following method:

  1. Create property to have strong reference to the provider.
  2. Send request with specific type. In this case you want to fetch list of posts so add Post model which conforms to Decodable and Encodable protocol.

3. Handle response! That’s all! :)

You can download the complete project for this tutorial here:

Conclusion

As you can see to build networking layer it’s not necessary to use third-party library with complicated logic. The biggest advantage of this solution is that it’s written in pure swift. To You can download the complete project for this tutorial here.