I am currently trying to implement the merging of two publishers. But I can't find a solution for my use case.
I want to merge 2 publishers that both emit an array of structs of the same type. I want the combined publisher to emit values when either one of the merged publishers emit a new value.
Basically this would be a use case for Publishers.CombineLatest
, but since my underlying publishers both emit values of the same type a merge
would be more fitting here. But Publishers.Merge
will not remember the last values of the merged publishers.
Therefore I would like to have a Publishers.CombineLatest
behaviour with a Publishers.Merge
operation. Is there something inside the Combine framework which can accomplish this kind of behaviour ?
Rough example what should happen:
Definitions:
PublisherA: emits -> [Value]
PublisherB emits -> [Value]
CombinedAB: -> [Value]
PublisherA changes: CombinedAB -> [NewA, OldB]
PublisherB changes: CombinedAB -> [OldA, NewB]
let a = CurrentValueSubject<[Int], Never>(["a", "b", "c"])
let b = CurrentValueSubject<[Int], Never>(["d", "e", "f"])
let combined = Publisher.AnyThing(a, b)
combined.sink {
print($0)
}
b.send(["g", "h", "i"])
Outputs:
["a", "b", "c", "d", "e", "f"]
["a", "b", "c", "g", "h", "i"]
So it's basically a Publishers.CombineLatest
but without emitting a tuple of (NewA,OldB) but instead already merged, because both values have the same type.
Any help is much appreciated.
Within the world of Combine, an object that emits such asynchronous values and events is called a publisher, and although the framework does ship with quite a large number of built-in publisher implementations, sometimes we might want to build our own, custom ones in order to handle specific situations.
What's a sink? While a complete explanation of Combine, publishers, subscribers, and sinks is beyond the scope of this article, for our purposes here it's probably enough to know that in Combine a sink is the code receives data and completion events or errors from a publisher and deals with them.
Subscribes to an additional publisher and publishes a tuple upon receiving output from either publisher.
Assuming that your combine operation is just concat of the subarrays you can do:
let a = CurrentValueSubject<[String], Never>(["a", "b", "c"])
let b = CurrentValueSubject<[String], Never>(["d", "e", "f"])
let combined = Publishers.CombineLatest(a, b).map(+)
combined.sink {
print($0) //["a", "b", "c", "d", "e", "f"] and ["a", "b", "c", "g", "h", "i"]
}
b.send(["g", "h", "i"])
I am not completely sure what you mean with "already merged".
If you want to have the latest emitted array always at the end of the combined array then you might need a scan
operator before the map(+)
to be able to compare with previous emissions and swap them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With