http://objc.to/A#https://www.vadimbulavin.com/modern-networking-in-swift-5-with-urlsession-combine-framework-and-codable/
Making HTTP requests is one of first things to learn when starting iOS development. Whether you implement networking from scratch, or use Alamofire and Moya, you often end up with a complex and tangled code. Especially, when it comes to requests chaining, running in parallel or cancelling.
Swift 5 system frameworks already provide us with all the tools that we need to write concise networking layer. In this article we’ll implement a promise-based networking agent by using vanilla Swift 5 APIs: Codable
, URLSession
and the Combine framework. To battle-test our networking layer, we’ll practice with several real-world examples that query Github REST API and synchronize the HTTP requests in chain and in parallel.
Agent
is a promise-based HTTP client. It fulfills and configures requests by passing a single URLRequest
object to it. The agent automatically transforms JSON data into a Codable
value and returns an AnyPublisher
instance:
import Combine
struct Agent {
// 1
struct Response<T> {
let value: T
let response: URLResponse
}
// 2
func run<T: Decodable>(_ request: URLRequest, _ decoder: JSONDecoder = JSONDecoder()) -> AnyPublisher<Response<T>, Error> {
return URLSession.shared
.dataTaskPublisher(for: request) // 3
.tryMap { result -> Response<T> in
let value = try decoder.decode(T.self, from: result.data) // 4
return Response(value: value, response: result.response) // 5
}
.receive(on: DispatchQueue.main) // 6
.eraseToAnyPublisher() // 7
}
}
The code requires some basic understanding of Combine. Here is the bird’s-eye overview of the Swift Combine framework.
Response<T>
carries both parsed value and a URLResponse
instance. The latter can be used for status code validation and logging.run<T>()
method is the single entry point for requests execution. It accepts a URLRequest
instance that fully describes the request configuration. The decoder is optional in case custom JSON parsing is needed.T
to be Decodable
in the run<T>()
method declaration.Response<T>
object and pass it downstream. It contains the parsed value and the URL response.AnyPublisher
.After implementing the networking core, we are ready to tackle several real-world examples.