I have this code
import Foundation
import Combine
let upstreamPublisher = Just("Hello, World!")
let sharedSubject = CurrentValueSubject<String, Never>("initial value")
// Create a multicast publisher and apply autoconnect
let multicastPublisher = upstreamPublisher
.multicast(subject: sharedSubject)
.autoconnect()
// Subscriber 1
multicastPublisher
.sink { value in
print("Subscriber 1 received value: \(value)")
}
// Subscriber 2
multicastPublisher
.sink { value in
print("Subscriber 2 received value: \(value)")
}
The output is:
Subscriber 1 received value: initial value
Subscriber 1 received value: Hello, World!
I read from an article that The first time you subscribe to it, it connects to the upstream publisher and starts the work immediately. This is useful in scenarios where the upstream publisher emits a single value and you can use a CurrentValueSubject to share it with subscribers.
. The first part makes sense to me, but I don't know what the second part of the sentence really means. How can we share the results with current value subject and autoconnect?
How can we share the results with current value subject and autoconnect?
This is already what your code is doing!
I assume you expected subscriber 2 to also receive the initial value and "Hello, World!", i.e. an output like this
Subscriber 1 received value: initial value
Subscriber 2 received value: initial value
Subscriber 2 received value: Hello, World!
Subscriber 1 received value: Hello, World!
This doesn't happen because Just
publishes synchronously. As soon as you call sink
, the subscriber is automatically connected to multicast
(because autoconnect
). As a result, Just
publishes its value and completes immediately. When you add the second subscriber, everything is already completed and it doesn't receive anything.
You can see this happening by adding .print("Subscriber 2")
before sink
. The output is:
Subscriber 2: receive subscription: (Multicast)
Subscriber 2: request unlimited
Subscriber 2: receive finished
If you turn the upstream into a publisher that doesn't publish values asynchronously, e.g. a network request, timer, delay
, etc, then both subscribers get values:
let upstreamPublisher = Just("Hello, World!")
.delay(for: 1, scheduler: DispatchQueue.main)
Make sure you store references to the AnyCancellable
s somewhere or the publisher will get cancelled before "Hello, World!" is published!
Of course, there is always the option of calling connect
manually.