Performing Network Operations with the Combine Framework in Swift

KD Knowledge Diet
3 min readMar 20, 2023

--

In this tutorial, we will explore how to use the Combine framework in Swift to perform network operations. Network operations are an essential part of mobile app development, and Combine provides a powerful way to handle asynchronous events.

First, we need a URL that will return the JSON data. For this example, we will be using the JSON Placeholder API, which is a fake online REST API for testing and prototyping. The following code creates a URL object for the API:

let url = URL(string: "https://jsonplaceholder.typicode.com/posts")!

Next, we will create a getPosts function that will use the URLSession class to perform the network operation. In the latest version of Combine, Apple has introduced two new functions for URLSession, which are dataTaskPublisher(for:) and dataTaskPublisher(for: URLRequest). We will use the dataTaskPublisher(for:) function to perform the network operation.

func getPosts() -> AnyPublisher<Data, Error> {
return URLSession.shared.dataTaskPublisher(for: url)
.map(\.data)
.eraseToAnyPublisher()
}

The getPosts() function returns an AnyPublisher<Data, Error>. The dataTaskPublisher(for:) function returns a tuple of (Data, URLResponse), and we are only interested in the data, so we use the map operator to extract the data from the tuple. Finally, we use the eraseToAnyPublisher() function to erase the publisher's type and make it an AnyPublisher<Data, Error>.

Now that we have our getPosts() function, let's use it to retrieve the JSON data. The following code shows how to use the sink function to receive the data:

var cancellable: AnyCancellable?
cancellable = getPosts()
.sink(receiveCompletion: { completion in
switch completion {
case .failure(let error):
print(error.localizedDescription)
case .finished:
break
}
}, receiveValue: { data in
let decoder = JSONDecoder()
if let posts = try? decoder.decode([Post].self, from: data) {
// Do something with the posts
}
})

The sink function takes two parameters, receiveCompletion and receiveValue. The receiveCompletion closure will be called once when the publisher completes, either with a success or a failure. In the receiveValue closure, we can use the JSONDecoder to decode the JSON data into a model. In this example, we will decode the data into an array of Post models.

To display the posts in a list view, we create a new struct called PostList. The following code shows how to define the PostList struct:

struct Post: Codable {
let userId: Int
let id: Int
let title: String
let body: String
}

struct PostList: View {
@State var posts: [Post] = []
var body: some View {
List(posts, id: \.id) { post in
VStack(alignment: .leading) {
Text(post.title)
.font(.headline)
Text(post.body)
.font(.subheadline)
}
}
.onAppear(perform: fetchData)
}

func fetchData() {
cancellable = getPosts()
.sink(receiveCompletion: { completion in
switch completion {
case .failure(let error):
print(error.localizedDescription)
case .finished:
break
}
}, receiveValue: { data in
let decoder = JSONDecoder()
if let posts = try? decoder.decode([Post].self, from: data) {
self.posts = posts
}
})

}
}

In the `PostList` struct, we define a state variable `posts`, which is an array of `Post` models. We then use the `List` view to display the posts in a list format. In the `onAppear` modifier, we call the `fetchData()` function to retrieve the data.

That’s it! We have successfully used the Combine framework to perform network operations and display the data in a list view.

In conclusion, using the Combine framework to perform network operations in Swift is a powerful way to handle asynchronous events. The framework provides many operators that make it easy to manipulate data and handle errors. With the getPosts() function, we were able to retrieve the JSON data, and with the PostList struct, we were able to display the data in a list view. This is just the tip of the iceberg, and there is much more to explore with the Combine framework.

--

--

KD Knowledge Diet

Software Engineer, Mobile Developer living in Seoul. I hate people using difficult words. Why not using simple words? Keep It Simple Stupid!