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: Stringenum 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.