Last active
September 9, 2022 19:14
-
-
Save antonio081014/3707b78ab7614ae7472098b4e54480fb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Combine | |
class FileSubscription<S: Subscriber>: Subscription | |
where S.Input == Data, S.Failure == Error { | |
// fileURL is the url of the file to read | |
private let fileURL: URL | |
private var subscriber: S? | |
init(fileURL: URL, subscriber: S) { | |
self.fileURL = fileURL | |
self.subscriber = subscriber | |
} | |
func request(_ demand: Subscribers.Demand) { | |
// Load the file at fileURL only when demand is | |
// greater than 0, meaning subscribers were added | |
// to this subscription and demand values | |
if demand > 0 { | |
do { | |
// Success case, data is loaded and this | |
// subscription finishes | |
let data = try Data(contentsOf: fileURL) | |
subscriber?.receive(data) | |
subscriber?.receive(completion: .finished) | |
} | |
catch let error { | |
// Failure case, this subscription finishes | |
// and propagates the error | |
subscriber?.receive( | |
completion: .failure(error) | |
) | |
} | |
} | |
} | |
// Set the subscriber reference to nil, cancelling | |
// the subscription | |
func cancel() { | |
subscriber = nil | |
} | |
} | |
struct FilePublisher: Publisher { | |
// The output type of FilePublisher publisher | |
// is Data, which will be the Data of the read file | |
typealias Output = Data | |
typealias Failure = Error | |
// fileURL is the url of the file to read | |
let fileURL: URL | |
func receive<S>(subscriber: S) where S : Subscriber, | |
Failure == S.Failure, Output == S.Input { | |
// Create a FileSubscription for the new subscriber | |
// and set the file to be loaded to fileURL | |
let subscription = FileSubscription( | |
fileURL: fileURL, | |
subscriber: subscriber | |
) | |
subscriber.receive(subscription: subscription) | |
} | |
} | |
// This is how to use it. | |
// Then, sink this Publisher and store the AnyCancellable to your local properties. | |
public final class DiskDataModelClient { | |
func get(from fileURL: URL) -> AnyPublisher<Data, Error> { | |
return FilePublisher(fileURL: fileURL) | |
.subscribe(on: DispatchQueue.global()) | |
.receive(on: DispatchQueue.main) | |
.eraseToAnyPublisher() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment