Here's my code to convert ReactiveSwift Signal Producers to Combine.Publishers
import ReactiveSwift
import Combine
/// convert SignalProducer<X, Never> -> Publisher<X, Never>
public struct ReactiveSwiftPublisher<Element>: Publisher {
public typealias Output = Element
public typealias Failure = Never
/// Subscription for ReactiveSwiftPublisher
class Subscription<SubscriberType: Subscriber>: Combine.Subscription where SubscriberType.Input == Element {
private var disposable: Disposable?
init(producer: SignalProducer<Element, Failure>, subscriber: SubscriberType) {
self.disposable = producer.startWithValues({
_ = subscriber.receive($0)
})
}
deinit {
self.disposable?.dispose()
}
func request(_ demand: Subscribers.Demand) {}
func cancel() {
self.disposable?.dispose()
}
}
private let producer: SignalProducer<Element, Failure>
public init(producer: SignalProducer<Element, Failure>) {
self.producer = producer
}
public func receive<S>(subscriber: S) where S : Subscriber, Failure == S.Failure, Output == S.Input {
let subscription = Subscription(producer: self.producer, subscriber: subscriber)
subscriber.receive(subscription: subscription)
}
}
extension SignalProducer where Error == Never {
public var publisher: ReactiveSwiftPublisher<Value> {
return ReactiveSwiftPublisher(producer: self)
}
}
Creating a publisher is fine
let x = MutableProperty<Int>(0)
var cancellables = Set<AnyCancellable>()
x.producer.publisher.sink {
print("$0")
}.store(in: &cancellables)
x.value = 33 // prints 33
but combining the latest doesn't yield a result
let x = MutableProperty<Int>(1)
let y = MutableProperty<Int>(0)
x.producer.publisher.combineLatest(y.producer.publisher).sink {
print($0) // does not print
}.store(in: &self.cancellables)
but for some reason adding a current value subject makes it work
// add this above the previous block
let subj = CurrentValueSubject<Int, Never>(0)
// and change the subscription to this
Publishers.CombineLatest3(x.producer.publisher, y.producer.publisher, self.subj.eraseToAnyPublisher()).sink {
print($0) // this prints (1, 0, 0)
}.store(in: &self.cancellables)
Does anyone know what I'm doing wrong in my ReactiveSwiftPublisher code?
I changed my Subscription function to set up the producer's subscription when the request is called
class Subscription<SubscriberType: Subscriber>: Combine.Subscription where SubscriberType.Input == Element {
private var disposable: Disposable?
private let subscriber: SubscriberType
private let producer: SignalProducer<Element, Failure>
init(producer: SignalProducer<Element, Failure>, subscriber: SubscriberType) {
self.producer = producer
self.subscriber = subscriber
}
deinit {
self.disposable?.dispose()
}
func request(_ demand: Subscribers.Demand) {
let subscriber = self.subscriber
self.disposable = self.producer.startWithValues({
_ = subscriber.receive($0)
})
}
func cancel() {
self.disposable?.dispose()
}
}
Here is a test
let a = MutableProperty<Int>(0)
let b = MutableProperty<Int>(1)
var disposable: AnyCancellable?
let aPub = a.producer.publisher
let bPub = b.producer.publisher
disposable = Publishers.CombineLatest(aPub, bPub).sink {
print("complete: \($0)")
} receiveValue: {
print("value: \($0)")
}
a.swap(3)
b.swap(3)
/*
Prints:
value: (0, 1)
value: (3, 1)
value: (3, 3)
*/