Forked from fjcaetano/DispatchQueue+DebounceThrottle.swift
Created
April 19, 2018 17:43
-
-
Save shakemno/104ccca664911b56ed4a327f42b6aeb9 to your computer and use it in GitHub Desktop.
Debounce + Throttle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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