Regulate is a lightweight library that brings the following time-based regulation operations for things that can emit values over times (and are not using reactive programming or AsyncSequence).
- Debounce (Outputs elements only after a specified time interval elapses between events)
- Throttle (Outputs either the most-recent or first element pushed by a producer in the specified time interval)
Regulate is entirely backed by Swift concurrency and limits the number of created Tasks to the minimum.
let regulator = Task.debounce(dueTime: .milliseconds(200)) { (value: Int) in print(value) } // the created `regulator` can be used across `Tasks` and each call to `regulator.push(x)` // will feed the regulation system // the execution of the provided closure will be debounced and executed 200ms after the last call to `push(x)`
Regulate also provides SwiftUI helpers to regulate buttons and bindings out of the box. You can give a look at the Sample app.
For a Button, it is as simple as:
Button { print("I've been hit (throttled)!") } label: { Text("Hit me") } .throttle(dueTime: .seconds(1))
For a Binding, there is a tiny bit of extra work:
@State private var text = "" @StateObject private var debouncer = Debouncer<String>(dueTime: .seconds(1)) ... TextField( text: self .$text .perform(regulator: debouncer) { text in print("regulated text \(text)") // you can perform any side effect here! } ) { Text("prompt") }
To use the Regulate library in a SwiftPM project,
add the following line to the dependencies in your Package.swift file:
.package(url: "https://github.com/sideeffect-io/Regulate"),
Include "Regulate" as a dependency for your executable target:
.target(name: "<target>", dependencies: ["Regulate"]),
Finally, add import Regulate to your source code.