Combine Framework In Swift -4
Using Combine for making a API Calls
Using Combine with API calls is very convenient due to operators and error handling methods from combine
Lets us look at a example:
Example URL: https://jsonplaceholder.typicode.com/posts"
Since URL session has support for combine, We can directly use it as a publisher which will emit the output and can be subscribed too.
First create the output model
struct Post:Identifiable, Codable {
let id: Int
let title: String
let body: String
let userId: Int
}
lets create a function which is kind of generic to different Models.
Where T can be any type of model which confirms to Identifiable and Codable protocol
struct GenricClass<T: Identifiable & Codable> {
private var session = URLSession.shared
var publisher: AnyPublisher< [T], Error>
init(url: URL) {
publisher = session.publisher(forUrl: url)
} func makeApiCall(withUrl url: URL) -> AnyPublisher< [T],Error> {
return session.publisher(forUrl: url)
}
}
In above example we have created a Struct class which can be initialized by any type of model(output) you are expecting and by using respective URL.
Now lets create and function which uses urlSession to make API call bu using publisher. Also using operators which will map the data and decode them using JSONDecoder and send it back to subscriber.
func publisher<T: Codable>(forUrl Url: URL, decoder: JSONDecoder = .init()) -> AnyPublisher<[T],Error> {
dataTaskPublisher(for: Url)
.map{$0.data}
.decode(type: [T].self, decoder: JSONDecoder())
.eraseToAnyPublisher()
}
When subscribed to this change, we will receive output in form of [Post].
func fetchData() {
subscriber = makeServiceCall(withUrl: url)
.sink(receiveCompletion: { (completion) in
switch completion {
case .finished:
break
case .failure(let error):
fatalError(error.localizedDescription)
}
}, receiveValue: {(value) in
print(“Recieved Value\(value)”)
})
}
We can further improve this by modifying its function call to handle nested Output