I want to transition from Combine to the Observation framework my question is how do I Debounce user input with the Observation framework there appears now way to do this. Any and all help is welcomed.
How to Debounce and Throttle Using @Observable
The expected path forward here is to combine (hey hey!) two tasks:
-
Turning an observed property into an async sequence of value changes.
-
Debouncing such a sequence.
The second task is covered by Swift Async Algorithms. The first task, however, is a challenge. The original SE-0395 proposed a general way to do this but that ran into problems during review. The proposal was recently accept with the async stuff moved into the Future Directions section.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Thanks Eskimo, could you point me in a direction for the first point above ? Where do I start to turn an observed property into an async sequence of value changes ? Thanks, A
@Dionysus-Design If you just want to debounce, you can use this code :
public actor Debouncer {
private let duration: Duration
private var isPending = false
public init(duration: Duration) {
self.duration = duration
}
public func sleep() async -> Bool {
if isPending { return false }
isPending = true
try? await Task.sleep(for: duration)
isPending = false
return true
}
}
Put this code in your Observable:
private let debouncer = Debouncer(duration: .seconds(0.5))
func checkEmailValidity() async {
guard await debouncer.sleep() else { return }
... do your debounced stuff here ...
}
And somewhere on your SwiftUI View for example:
.onChange(of: viewModel.email) { Task { await viewModel.checkEmailValidity() } }
It seems that the timer is only set on the first key stroke. How would I reset timer to zero on each stroke to better implement debounce?