Building a SwiftUI app using MVVM architecture — Part 4: Implementing a network request with Combine
A view will often use an observable object to reflect the latest data fetched from a web-service.
Apple has introduced the Combine framework, a way to handle asynchronous events by combining event-processing operators.
If you’re not familiar with Combine, checkout my article here.
In Headlines, I needed to retrieve some data for each category and return a publisher containing the requested elements once all networks calls had completed.
Using the built-in `dataTaskPublisher` comes in handy to create these multiple asynchronous requests and merge them into a single publisher sequence.
The collect() operator allowed me to group all the elements from that sequence into a single array.
typealias HeadlinesResult = AnyPublisher<(HeadlinesSection, Result), Error>class Webservice {
func fetch(preferences: UserPreferences) -> AnyPublisher<[(HeadlinesSection, Result)], Never> {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601 let recency = preferences
.recencies
.filter { $0.isSelected }
.first?.date
let country = preferences
.countries
.filter { $0.isSelected }
.first?.country
let categories = preferences
.categories
.filter { $0.isSelected }
let publishers = categories.map { category -> HeadlinesResult in let endpoint = Endpoint.search(
recency: recency ?? .today,
country: country ?? .france,
category: category.name.rawValue
) let publisher = URLSession.shared.dataTaskPublisher(for: endpoint.url!)
.retry(2)
.map { $0.data }
.decode(type: Result.self, decoder: decoder)
.receive(on: RunLoop.main)
.map { (category.name, $0) }
.eraseToAnyPublisher() return publisher
} return Publishers.MergeMany(publishers)
.collect()
.replaceError(with: [])
.eraseToAnyPublisher()
}
}
Chaining operators on the `dataTaskPublisher` enable us to implement successive operations on the upstream publisher delivering the expected HeadlinesResult type.
Combine facilitates the handling of asynchronous calls using a declarative approach resulting in clarity and code legibility.
SwiftUI and Combine works well together as they provide both that very declarative approach.
Continue with Part 5: Connecting the models with the UI using MVVM.