Instantly share code, notes, and snippets.

Embed
What would you like to do?
Debounce + Throttle
import Dispatch
private var throttleWorkItems = [AnyHashable: DispatchWorkItem]()
private var lastDebounceCallTimes = [AnyHashable: DispatchTime]()
private let nilContext: AnyHashable = arc4random()
public extension DispatchQueue {
/**
- parameters:
- deadline: The timespan to delay a closure execution
- context: The context in which the throttle should be executed
- action: The closure to be executed
Delays a closure execution and ensures no other executions are made during deadline
*/
public func throttle(deadline: DispatchTime, context: AnyHashable? = nil, action: @escaping () -> Void) {
let worker = DispatchWorkItem {
defer { throttleWorkItems.removeValue(forKey: context ?? nilContext) }
action()
}
asyncAfter(deadline: deadline, execute: worker)
throttleWorkItems[context ?? nilContext]?.cancel()
throttleWorkItems[context ?? nilContext] = worker
}
/**
- parameters:
- interval: The interval in which new calls will be ignored
- context: The context in which the debounce should be executed
- action: The closure to be executed
Executes a closure and ensures no other executions will be made during the interval.
*/
public func debounce(interval: Double, context: AnyHashable? = nil, action: @escaping () -> Void) {
if let last = lastDebounceCallTimes[context ?? nilContext], last + interval > .now() {
return
}
lastDebounceCallTimes[context ?? nilContext] = .now()
async(execute: action)
// Cleanup & release context
throttle(deadline: .now() + interval) {
lastDebounceCallTimes.removeValue(forKey: context ?? nilContext)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment