Open kevinrenskers opened 4 years ago
Hey @kevinrenskers, check out the latest release. I've added toPublisher()
extension method to SignalProtocol
that converts ReactiveKit signal into Combine publisher, as well as toSignal()
extension on Publisher
that converts it the other way around.
Very cool! 🎉
I love ReactiveKit's easy way to wrap old-fashioned async code with callbacks into Signals (https://github.com/DeclarativeHub/ReactiveKit#wrapping-asynchronous-calls-into-signals). I found it quite hard to do the same in pure Combine, so these new extensions will really help to go from async calls to Combine publishers. But, let's say I would want to skip the ReactiveKit in-between step at some point, would you suggest a similar route as the code in https://github.com/DeclarativeHub/ReactiveKit/blob/master/Sources/Combine.swift#L51? With the nested struct etc?
@kevinrenskers yeah, I miss that in Combine too. One approach could be to implement Signal in Combine, it should be pretty easy. Here is my quick attempt:
public struct Signal<Output, Failure: Error>: Combine.Publisher {
private class Subscription: Combine.Subscription {
let producer: (AnySubscriber<Output, Failure>) -> Combine.AnyCancellable
let subscriber: AnySubscriber<Output, Failure>
var cancellable: Combine.AnyCancellable?
init(producer: @escaping (AnySubscriber<Output, Failure>) -> Combine.AnyCancellable, subscriber: AnySubscriber<Output, Failure>) {
self.producer = producer
self.subscriber = subscriber
}
func request(_ demand: Combine.Subscribers.Demand) {
cancellable = producer(subscriber)
}
func cancel() {
cancellable?.cancel()
}
}
private let producer: (AnySubscriber<Output, Failure>) -> Combine.AnyCancellable
public init(_ producer: @escaping (AnySubscriber<Output, Failure>) -> Combine.AnyCancellable) {
self.producer = producer
}
public func receive<S>(subscriber: S) where S: Combine.Subscriber, Failure == S.Failure, Output == S.Input {
let subscription = Subscription(producer: producer, subscriber: AnySubscriber(subscriber))
subscriber.receive(subscription: subscription)
}
}
let signal = Signal<Int, TestError> { subscriber in
subscriber.receive(1)
subscriber.receive(2)
subscriber.receive(completion: .finished)
return Combine.AnyCancellable {
print("Cancelled")
}
}
signal.sink(receiveCompletion: { print($0) }, receiveValue: { print($0) })
I have a UIKit app, where I am starting to integrate a bit of SwiftUI into (via UIHostingController). My SwiftUI views need to use Combine (
@State
, or@ObservedObject
+@Published
for example), but I'd still like these views to work with my existing ReactiveKit Signals. Is this possible without writing a bunch of boilerplate code? Has anyone else tried to make ReactiveKit and Combine work together in one app?