In this section, you will explore how to make REST API calls using Swift's concurrency
async
await
model and the URLSession
framework.Swift's concurrency
async
await
features, introduced in Swift 5.5, allow us to write asynchronous code in a more concise and readable manner.Previously, the API used a closure based approach that invoked the callback provided when API requests were finished. Now, powered by Swift concurrency, your thread will suspend during API calls.
So make sure you are making API requests in the background queue to avoid unresponsive UI.
How to make REST API call in iOS
Making a REST API call on iOS can be done using the built-in URLSession class.
TheURLSession
class and related classes provide an API for downloading data from and uploading data to endpoints indicated by URLs. Your app can also use this API to perform background downloads when your app isn’t running or, in iOS, while your app is suspended. You can use the relatedURLSessionDelegate
andURLSessionTaskDelegate
to support authentication and receive events like redirection and task completion. - URLSession Documentation
This class is available as part of the Foundation framework provided by Apple. The only thing you need to do to use this class is import the framework into the Swift file where you are going to use URLSession.
import Foundation URLSession.shared // you can use URLSession.shared becuase you import Foundation
These examples below will should you how to call a REST API endpoint using Swift URLSession with new
async
await
feature.GET Request Example
A GET request is used to fetch data from a server by supplying information in the URL endpoint.
let baseUrl = "https://jsonplaceholder.typicode.com" let endpoint = "/posts/1" func getRequest() async { if let url = URL(string: baseUrl + endpoint) { do { let(data, _) = try await URLSession.shared.data(from: url) if let responseData = try JSONSerialization .jsonObject(with: data) as ? [String: Any] { print("GET Response:", responseData) } } catch { print("GET Request Failed:", error) } } } func main() async { await getRequest() } await main()
In this example, you use the
async
keyword to define an asynchronous function. You then create a URL
using the base URL and endpoint and use URLSession.shared.data(from:)
to fetch the data asynchronously.You decode the JSON response using
JSONSerialization
and print the result.POST Request Example
A POST request is used to send data to a server within the request body.
This is the second most common HTTP method iOS applications use. The example use case is to create user information for the first time or create a new purchase for a specific product in an e-commerce app.
let baseUrl = "https://jsonplaceholder.typicode.com" let endpoint = "/posts" func postRequest() async { let dataToSend: [String: Any] = [ "name": "Jack", "hobby": "Coding", "userId": 1 ] if let url = URL(string: baseUrl + endpoint) { var request = URLRequest(url: url) request.httpMethod = "POST" request.addValue("application/json", forHTTPHeaderField: "Content-Type") do { request.httpBody = try JSONSerialization.data(withJSONObject: dataToSend) let (data, _) = try await URLSession.shared.data(for: request) if let responseData = try JSONSerialization.jsonObject(with: data) as? [String: Any] { print("POST Response:", responseData) } } catch { print("POST Request Failed:", error) } } } func main() async { await postRequest() } await main()
Here, you create a POST request by configuring a
URLRequest
with the POST
method, add Content-Type
headers, and request body. You then use URLSession.shared.data(for:)
to send the request asynchronously and decode the JSON response.The difference with a GET request is that you need to create a
URLRequest
because you need to pass data in the request body.Actually, our previous GET request also created a
URLRequest
, but because it is a common pattern to create a URLRequest
with an endpoint, Apple already provided you with the convenience method to make API calls only by supplying a URL
instance.PATCH Request Example
A PATCH request is used to update existing data on the server within the request body.
When you have a user profile screen, you usually create a profile update feature. This is the perfect example where a PATCH request can be used rather than a POST request.
let baseUrl = "https://jsonplaceholder.typicode.com" let endpoint = "/posts/1" func patchRequest() async { let dataToUpdate: [String: Any] = [ "hobby": "Fishing" ] if let url = URL(string: baseUrl + endpoint) { var request = URLRequest(url: url) request.httpMethod = "PATCH" request.addValue("application/json", forHTTPHeaderField: "Content-Type") do { request.httpBody = try JSONSerialization.data(withJSONObject: dataToUpdate) let(data, _) = try await URLSession.shared.data(for: request) if let responseData = try JSONSerialization.jsonObject(with: data) as ? [String: Any] { print("PATCH Response:", responseData) } } catch { print("PATCH Request Failed:", error) } } } func main() async { await patchRequest() } await main()
Similarly to the POST example, we configure a
URLRequest
with the necessary details and use URLSession.shared.data(for:)
to send the request and handle the response asynchronously.DELETE Request Example
A DELETE request is used to remove data from the server by providing information within the URL endpoint.
If user wants to remove their comment for a product in an e-commerce app, you can make an API call using this HTTP method.
let baseUrl = "https://jsonplaceholder.typicode.com" let endpoint = "/posts/1" func deleteRequest() async { if let url = URL(string: baseUrl + endpoint) { var request = URLRequest(url: url) request.httpMethod = "DELETE" do { let (data, _) = try await URLSession.shared.data(for: request) if let responseData = try JSONSerialization.jsonObject(with: data) as? [String: Any] { print("DELETE Response:", responseData) } } catch { print("DELETE Request Failed:", error) } } } func main() async { await deleteRequest() } await main()
In the DELETE example, we configure a
URLRequest
with the DELETE method and send the request using URLSession.shared.data(for:)
. The response is then processed in the same way as in the previous examples.Wrapping Up
Congratulations! You've learned how to make various REST API calls using Swift's concurrency model and the
URLSession
framework. Swift's async
await
syntax and concurrency features provide a more readable and structured way to write asynchronous code.Feel free to explore more advanced topics related to Swift concurrency and the URLSession framework in the official Swift documentation and additional resources on Swift programming.