Last active
December 27, 2023 01:27
-
-
Save grafele/227c7c04d04837fb0a91d97a25f22424 to your computer and use it in GitHub Desktop.
Easiest way of creating a Combine-Publisher using a closure. Equivalent to Observable.create from RxSwift
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
extension Publishers { | |
public struct Anonymous<Output, Failure: Swift.Error>: Publisher { | |
private var closure: (AnySubscriber<Output, Failure>) -> Void | |
public init(closure: @escaping (AnySubscriber<Output, Failure>) -> Void) { | |
self.closure = closure | |
} | |
public func receive<S>(subscriber: S) where S : Subscriber, Anonymous.Failure == S.Failure, Anonymous.Output == S.Input { | |
let subscription = Subscriptions.Anonymous(subscriber: subscriber) | |
subscriber.receive(subscription: subscription) | |
subscription.start(closure) | |
} | |
} | |
} | |
extension Subscriptions { | |
final class Anonymous<SubscriberType: Subscriber, Output, Failure>: Subscription where SubscriberType.Input == Output, Failure == SubscriberType.Failure { | |
private var subscriber: SubscriberType? | |
init(subscriber: SubscriberType) { | |
self.subscriber = subscriber | |
} | |
func start(_ closure: @escaping (AnySubscriber<Output, Failure>) -> Void) { | |
if let subscriber = subscriber { | |
closure(AnySubscriber(subscriber)) | |
} | |
} | |
func request(_ demand: Subscribers.Demand) { | |
// Ignore demand for now | |
} | |
func cancel() { | |
self.subscriber = nil | |
} | |
} | |
} | |
extension AnyPublisher { | |
static func create(_ closure: @escaping (AnySubscriber<Output, Failure>) -> Void) -> AnyPublisher<Output, Failure> { | |
return Publishers.Anonymous<Output, Failure>(closure: closure) | |
.eraseToAnyPublisher() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Was searching for a way to start a Combine pipeline from a closure and found your snippet.
After playing around with it, I wondered if there was no easier way to accomplish this, esp. I didn't want to have to manage the subscriber in the closure with which the publisher was created. So I came up with the following.
Usage site looks like this:
Just.go { /* do some stuff and return a value */ }
.What do you think?