Saeid Rezaeisadrabadi
2 min readMay 4, 2022

Hello dear readers,

let’s start to create a network layer with the async/await in swift.

One of the major new features that are being introduced in Swift 5.5 is async/await, and as part of their latest SDKs, Apple has also updated many of their built-in asynchronous APIs to take advantage of this new feature.

Loading some form of Data using a standard GET request is arguably the most common type of network call that apps perform on a regular basis, and using async/await, this can now be done using just a single line of code:

let (data, response) = try await URLSession.shared.data(from: url)

You can use response to verify your response. I will show it in APIRequest class.

For this story, I will make an HTTP get request to the Random Data API. I will call the computer endpoint, to get random data for every HTTP request.

I created a ResponseModel to map responses from the API.

struct ComputerResponseModel: Decodable {
let id: Int
let uid: String
let platform: String
let type: String
let os: String
let stack: String
enum CodingKeys: String, CodingKey {
case id
case uid
case platform
case type
case os
case stack
}
}

To demonstrate that nothing has to be changed when I use async/await when making API requests, I created RequestProtocol. Your request class is the only change.

final class APIRequest: APIRequestProtocol {func get(request: URLRequest) async throws -> Result<Data, Error> {
let (data, response) = try await URLSession.shared.data(for: request)
return verifyResponse(data: data, response: response)
}
private func verifyResponse(data: Data, response: URLResponse) -> Result<Data, Error> {
guard let httpResponse = response as? HTTPURLResponse else {
return .failure(APIError.unknown)
}
switch httpResponse.statusCode {
case 200...299:
return .success(data)
case 400...499:
return .failure(APIError.badRequest)
case 500...599:
return .failure(APIError.serverError)
default:
return .failure(APIError.unknown)
}
}
}

The get method will be called with the proper URLRequest.

As an example, I will call a random computer API in the ComputerAPI class:

func fetchRandomComputer() async throws -> ComputerResponseModel? {
let request = ComputerAPIRequestProtocol.getRandomComputer
guard let urlRequest = request.urlRequest() else {
throw ComputerAPIError.nilRequest
}
let apiData = try await apiRequest.get(request: urlRequest)
switch apiData {
case .success(let data):
let decoder = JSONDecoder()
do {
return try decoder.decode(ComputerResponseModel.self, from: data)
} catch {
throw ComputerAPIError.invalidResponseFormat
}
case .failure(let error):
throw error
}
}

and to use this in my ViewController, I used Task:

func getRandomComputer() {
Task {
do {
let computer = try await api.fetchRandomComputer()
textView.text = computer?.description
} catch {
textView.text = "\(error)"
}
}
}

based on your application architecture, you can use it everywhere.

There you have it! Making a network request using async/await is pretty straightforward, and we gain tons of benefits by just simply using it.

You can find the full source code here.

Saeid Rezaeisadrabadi
Saeid Rezaeisadrabadi

Written by Saeid Rezaeisadrabadi

Over 8 years of experience in iOS software development

No responses yet