Using Combine and Async to Create Robust and Efficient Network APIs

Tatenda Kabike
DVT Software Engineering
4 min readJan 27, 2023

Creating a responsive and efficient mobile app can be challenging due to the constant flow of data and events from network traffic, data input and callbacks. To help developers meet this challenge, Apple released the Combine framework in 2019 and the Async/Await feature for the Swift programming language in June 2021. These tools allow developers to create smooth, fast and responsive apps by efficiently handling events and avoiding the dreaded callback hell.

In this blog, we’ll show you how to use the Combine framework and Async/Await feature to create a news app with a real-time search feature. We’ll be using SwiftUI and MVVM architecture to structure our code. You’ll need to sign up for a free account with the News API to get started. You can do this here. At the end of this blog, you’ll find the source code for the project.

Fetching data using Async/Await

First, we’ll create a method to implement an asynchronous call to News API. Below is a snippet of the method.

With the above code, we are fetching data from a URL by asynchronously calling await on URLSession.shared.data(for: ). We have wrapped this call inside a try catch block, to provide error handling, but in this case, we are returning an empty array if an error occurs. Feel free to extend it and add your preferred error-handling code.

After the network call, the results are stored in articles variable, and finally, we will map the results to custom article array. Another benefit we can get by implementing Async/Await is that it is clean and easy to read.

Creating the View Model

The view model will play a very big and pivotal role as we combine all the pieces we need in our app. I will explain the parts that Combine plays in conjunction with async/await. Below is a snippet of our view model:

In our view model, the “@Published” annotated variables play a key role in publishing the latest changes from our view models to our UI. They are part and parcel of Combine. Behind the wrapper, some abstracted Combine code is running in the background. Apple has done a great job by bringing together Combine and SwiftUI, making it easy to manage state and publishing changes to the UI. Next, we will look for how the Combine pipeline is triggered as we search for articles from News API.

Combine Pipeline.

The searchTerm is a published variable making it a qualified Combine publisher, allowing us to subscribe to it and use it as our starting point for a Combine pipeline. We initialise this in our view model initializer method.

  1. The debounce operator publishes elements only after a specified time interval elapses between events. This operator is useful to process bursty or high-volume event streams where you need to reduce the number of values delivered downstream to a specific rate. In our case, we are using 0.8 as our interval.
  2. We can further reduce the number of requests by removing any duplicate API calls using the removeDuplicates operator. When the user searches for articles, the variables passed in the pipeline might produce duplicates, and we need to take care of those events.
  3. Using the handleEvents operator, we can take advantage to initialise the state of the variable we will use to initialise the progress view. This makes it easy to implement this feature despite many requests being sent to the API.
  4. Now our searchTerm has reached a stage where we need to use it. We will make use of the flatMap to map the string and use it to make requests.
  5. We will need to make our asynchronous call to our API, so we need to establish an asynchronous context. Wrap our call in a Task; once searchArticles returns results, we resolve the promise by sending the result as a success down the pipeline.
  6. To make sure we make changes to the UI only from the main thread, we call . receive(on: DispatchQueue.main)
  7. Next, we add the eraseToAnyPublisher() to wrap the real type of our published value result.
  8. Since we know the result has been published, we will need to dismiss our progress view on the UI side. You will see that in a bit. So we utilise the handleEvents operator again to update isSearching variable to false.
  9. Finally, we use the assign operator to assign the result, which is an array of articles, and of course, the result will be published and then subscribed to on the UI side. The image below shows the result ([ArticleDetail]) that we will assign at the end of the pipeline.

Now we are ready to jump to the UI.

Connecting to the UI

The main thing in the code above that we need to pay attention to is the @StateObject wrapper on viewModel variable. This acts as a subscriber, in this case, subscribing to an observable object — our view model as it extends an ObservableObject. All the changes, states and events in our view model are published to our UI through the observable variable. That's magical!

SwiftUI is tightly integrated with Combine, making it easy to develop apps with surprisingly little code.

I hope you enjoyed reading this article. You can get the source code from the link below.

Thanks for reading, and let’s keep coding!

--

--

Tatenda Kabike
DVT Software Engineering

IOS mobile developer, content creator, i love experimenting with ARKit & CoreML. I love travelling and nature when i am off the machine.