Reputation: 1619
I'm struggling to understand why no values are received to sink
in the underlying code.
func somePublisher() -> AnyPublisher<Bool, Never> {
let subject = PassthroughSubject<Bool, Never>()
subject.send(true)
subject.send(completion: .finished)
return subject.eraseToAnyPublisher()
}
somePublisher()
.first()
.sink { _ in
print("Completed")
} receiveValue: {
print("Received \($0)")
}
.store(in: &sinks)
Output:
Completed
It looks like values are not received by the publishers down the stream if it was finished before it was connected. Is that right? How could I fix that if my publisher can finish synchronously?
Upvotes: 4
Views: 3601
Reputation: 20600
I was struggling with this same problem and I made use of RunLoop.current
to overcome it...
func somePublisher() -> AnyPublisher<Bool, Never> {
let subject = PassthroughSubject<Bool, Never>()
RunLoop.current.perform {
// Delay send/completion until next run loop to give subscribers a chance to subscribe
subject.send(true)
subject.send(completion: .finished)
}
return subject.eraseToAnyPublisher()
}
somePublisher()
.first()
.sink { _ in
print("Completed")
} receiveValue: {
print("Received \($0)")
}
.store(in: &sinks)
Upvotes: 0
Reputation: 19912
PassthroughSubject
receives a value and passes it along, it doesn't store the value so if you subscribe to it after the value passed through it, you won't receive it.
You can use CurrentValueSubject
, which will store the latest value and resend it whenever somebody subscribes to it.
All of this is moot if you send completion: .finished
though. A completed publisher won't send any values to a subscriber because it's completed.
This is your fixed code:
func somePublisher() -> AnyPublisher<Bool, Never> {
let subject = CurrentValueSubject<Bool, Never>(true)
return subject.eraseToAnyPublisher()
}
var bag: Set<AnyCancellable> = []
somePublisher()
.first()
.sink { _ in
print("Completed")
} receiveValue: {
print("Received \($0)")
}
.store(in: &bag)
Upvotes: 5