I have a PassthroughSubject
which is connected to a ScrollView
and it emits while it scrolls. I want the subject to emit the current scroll value, but only once per second. I tried throttle
and debounce
, but they don't seem to be doing what I need.
Like this, I can see every time it emits while I'm scrolling, so my base setup of scroll detection is working well.
scrollSubject
.sink { value in
print(value)
}
.store(in: &subscription)
But when I try to use either of these:
.throttle(for: 1, scheduler: RunLoop.main, latest: false)
(tried latest: true
also)`
.debounce(for: 1, scheduler: RunLoop.main)
What happens is they are not emitting while I'm scrolling, only after I've stopped it emits the latest value. How is it possible to achieve the desire behaviour?
What you are describing sounds like the sample
operator available in other reactive programming libraries. It can be implemented in this way like @Alexander is describing:
extension Publisher {
func sample(
every interval: TimeInterval,
on runLoop: RunLoop,
in mode: RunLoop.Mode
) -> AnyPublisher<Output, Failure> {
let timer = Timer.publish(every: interval, on: runLoop, in: mode)
.autoconnect()
.mapError { $0 as! Failure }
return combineLatest(timer)
.map(\.0)
.eraseToAnyPublisher()
}
}