Skip to content

Instantly share code, notes, and snippets.

@bguidolim
Created November 20, 2023 16:02
Show Gist options
  • Save bguidolim/bda6b50f2914a11cd76c12684184e344 to your computer and use it in GitHub Desktop.
Save bguidolim/bda6b50f2914a11cd76c12684184e344 to your computer and use it in GitHub Desktop.
import Foundation
public final class Debouncer {
public var isCancelled: Bool { workItem.isCancelled }
private lazy var queue: DispatchQueue = {
DispatchQueue(label: "com.traderepublic.debouncer", target: .global())
}()
private var workItem: DispatchWorkItem = .init(block: {})
private var interval: TimeInterval
private var restart: Bool
private var lastExecution: Date?
public init(interval: TimeInterval, restart: Bool = true) {
self.interval = interval
self.restart = restart
}
public func debounce(_ action: @escaping (() -> Void)) {
debounce(on: queue, action)
}
public func debounce(on queue: DispatchQueue, _ action: @escaping (() -> Void)) {
workItem.cancel()
workItem = DispatchWorkItem(block: action)
let nextExecution: Date
let now: Date = .init()
if restart {
nextExecution = now + interval
} else {
if let lastExecution: Date = self.lastExecution {
let lastExecutionInterval: TimeInterval = now.timeIntervalSince(lastExecution)
nextExecution = now + max(0, interval - lastExecutionInterval)
} else {
nextExecution = now
}
}
queue.asyncAfter(deadline: .now() + nextExecution.timeIntervalSinceNow, execute: workItem)
lastExecution = nextExecution
}
public func cancel() {
workItem.cancel()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment