Add throttle and debounce extensions for DispatchQueue
This commit is contained in:
parent
e1b0530520
commit
b2a33fecc5
|
@ -13,6 +13,7 @@ This version also cleans up the code and makes changes to conform to the latest
|
|||
### ✨ New features
|
||||
|
||||
* `Calendar+Date` has new `same` functions to provide the comparison date.
|
||||
* `DispatchQueue+Throttle` has new `throttle` and `debounce` functions.
|
||||
* `String+Split` has a new `split(by:)` components splitting function.
|
||||
* `Url+Global` has a new `userSubscriptions` url.
|
||||
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// DispatchQueue+Throttle.swift
|
||||
// SwiftKit
|
||||
//
|
||||
// Created by Daniel Saidi on 2021-09-17.
|
||||
// Copyright © 2021 Daniel Saidi. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
private var lastDebounceCallTimes = [AnyHashable: DispatchTime]()
|
||||
private let nilContext: AnyHashable = arc4random()
|
||||
private var throttleWorkItems = [AnyHashable: DispatchWorkItem]()
|
||||
|
||||
public extension DispatchQueue {
|
||||
|
||||
/**
|
||||
Try to perform a debounced operation.
|
||||
|
||||
Executes a closure and ensures that no other executions
|
||||
will be made during the provided `interval`.
|
||||
|
||||
- parameters:
|
||||
- interval: The time to delay a closure execution, in seconds
|
||||
- context: The context in which the debounce should be executed
|
||||
- action: The closure to be executed
|
||||
*/
|
||||
func debounce(interval: Double, context: AnyHashable? = nil, action: @escaping () -> Void) {
|
||||
let worker = DispatchWorkItem {
|
||||
defer { throttleWorkItems.removeValue(forKey: context ?? nilContext) }
|
||||
action()
|
||||
}
|
||||
|
||||
asyncAfter(deadline: .now() + interval, execute: worker)
|
||||
throttleWorkItems[context ?? nilContext]?.cancel()
|
||||
throttleWorkItems[context ?? nilContext] = worker
|
||||
}
|
||||
|
||||
/**
|
||||
Try to perform a throttled operation.
|
||||
|
||||
Performs the first performed operation, then delays any
|
||||
further operations until the provided `interval` passes.
|
||||
|
||||
- parameters:
|
||||
- interval: The time to delay a closure execution, in seconds
|
||||
- context: The context in which the throttle should be executed
|
||||
- action: The closure to be executed
|
||||
*/
|
||||
func throttle(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)
|
||||
debounce(interval: interval) {
|
||||
lastDebounceCallTimes.removeValue(forKey: context ?? nilContext)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue