Skip to content

Instantly share code, notes, and snippets.

@SixFiveSoftware
Created March 7, 2020 21:43
Show Gist options
  • Save SixFiveSoftware/299855f3f318d32b35f2ad8c3319fed3 to your computer and use it in GitHub Desktop.
Save SixFiveSoftware/299855f3f318d32b35f2ad8c3319fed3 to your computer and use it in GitHub Desktop.
//
// Remote.swift
//
// Created by BJ Miller on 3/7/20.
// Copyright © 2020 BJ Miller. All rights reserved.
//
import Foundation
import Combine
class AbstractRemote<T>: ObservableObject {
@Published var result: Result<T, Error>? = nil
fileprivate var transform: (Data) -> T?
private var cancellable: AnyCancellable?
var value: T? {
guard let result = result else { return nil }
switch result {
case .failure(_): return nil
case .success(let item): return item
}
}
fileprivate var url: URL
init() {
self.url = URL(string: "http://foo.com")!
self.transform = { _ in return nil }
}
func fetch() {
cancellable = URLSession.shared.dataTaskPublisher(for: url)
.map { $0.data }
.compactMap(self.transform)
.sink(receiveCompletion: { (completion: Subscribers.Completion<URLError>) in
switch completion {
case .failure(let err):
print("error: \(err.localizedDescription)")
DispatchQueue.main.async { self.result = .failure(err) }
case .finished: break
}
}, receiveValue: { (item: T) in
DispatchQueue.main.async { self.result = .success(item) }
})
}
}
class Remote<T: Decodable>: AbstractRemote<T> {
init(url: URL) {
super.init()
self.url = url
self.transform = { try? Decoders.defaultDecoder.decode(T.self, from: $0) }
}
}
class RemoteData<T>: AbstractRemote<T> {
init(url: URL, transform: @escaping (Data) -> T?) {
super.init()
self.url = url
self.transform = transform
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment