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.

--

--