Consider the following synthetic scenario:
import Combine
let publisher1 = PassthroughSubject<Int, Never>().eraseToAnyPublisher()
let publisher2 = PassthroughSubject<Int, Never>()
publisher1.sink { value in
publisher2.send(value)
}
We have 2 publishers, I'd like to propagate any value of the publisher1
to the publisher2
. The code I've shown does the job, but I'm interested whether there is a cleaner, declarative approach to this.
Note: both publisher1
and publisher2
are of the same type.
Details on the problem
publisher2
is a part of the API that is exposed by the "core" class. The "core" class has a "has a" relationship to a "child" class which in turn has a publisher1
as it's API.
Over the lifetime of the "core" class, the "child" class can be allocated and deallocated multiple times. This should be transparent to the subscribers of the "core" class which won't need to subscribe to the publisher2
.
Code:
import UIKit
import Combine
class ChildClass {
let publisher1 = PassthroughSubject<Int, Never>().eraseToAnyPublisher()
}
class CoreClass {
let publisher2 = PassthroughSubject<Int, Never>()
private var childClass: ChildClass?
init() {
allocateChildClass()
}
func allocateChildClass() {
let child = ChildClass()
childClass = child
// Any way to simplify this?
child.publisher1.sink { value in
publisher2.send(value)
}
}
func deallocateChildClass() {
childClass = nil
}
}
class Client {
let core = CoreClass()
init() {
// Doesn't care about allocating or deallocating of the ChildClass
core.publisher2.sink { value in
print(value)
}
}
}
Trying to subscribe one publisher to another doesn't work:
publisher2
.subscribe(publisher1)
No exact matches in call to instance method 'subscribe'
It is a delightful feature of PassthroughSubject that it is both a publisher and an operator: a Subject can be chained directly to a pipeline.
So just say
publisher1.subscribe(publisher2)
and you're all set.