Skip to content

Instantly share code, notes, and snippets.

@ole
Last active November 7, 2019 02:53
Show Gist options
  • Save ole/39ed233400d7e68b953be235ef7a9281 to your computer and use it in GitHub Desktop.
Save ole/39ed233400d7e68b953be235ef7a9281 to your computer and use it in GitHub Desktop.
Combine with URLSession.dataTaskPublisher
// https://twitter.com/BelleBCooper/status/1192173933983715328
import Combine
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
/// JSON format:
///
/// {
/// "userId": 1,
/// "id": 1,
/// "title": "delectus aut autem",
/// "completed": false
/// }
struct Todo: Decodable {
var userId: Int
var id: Int
var title: String
var completed: Bool
}
let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")!
// Variant 1
// This works by not using the .decode publisher at all.
let subscription1 = URLSession.shared
.dataTaskPublisher(for: url)
.print("1-dataTask")
.tryMap { result -> (model: Todo, response: URLResponse) in
let model = try JSONDecoder().decode(Todo.self, from: result.data)
return (model, result.response)
}
.print("1-decoded")
.sink(receiveCompletion: { _ in }, receiveValue: { _ in })
// Variant 2
let dataTaskPublisher = URLSession.shared
.dataTaskPublisher(for: url)
.print("2-dataTask")
// Prevent the network request from executing twice
// See http://www.cocoawithlove.com/blog/twenty-two-short-tests-of-combine-part-2.html
.multicast { PassthroughSubject() }
.autoconnect()
let responsePublisher = dataTaskPublisher.map { $0.response }.mapError { $0 as Error }
let modelPublisher = dataTaskPublisher
.map { $0.data }
.decode(type: Todo.self, decoder: JSONDecoder())
.mapError { $0 as Error }
let subscription2: AnyCancellable = responsePublisher.zip(modelPublisher)
.print("2-zipped")
.sink(receiveCompletion: { _ in }, receiveValue: { _ in })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment