Skip to content

Instantly share code, notes, and snippets.

@ostholz
Last active June 11, 2020 09:10
Show Gist options
  • Save ostholz/5e86319645af93127e5d1d51719d651a to your computer and use it in GitHub Desktop.
Save ostholz/5e86319645af93127e5d1d51719d651a to your computer and use it in GitHub Desktop.
// copy from https://www.craftappco.com/blog/2018/5/30/simple-throttling-in-swift
class Throttler {
private var workItem: DispatchWorkItem = DispatchWorkItem(block: {})
private var previousRun: Date = Date.distantPast
private let queue: DispatchQueue
private let minimumDelay: TimeInterval
init(minimumDelay: TimeInterval, queue: DispatchQueue = DispatchQueue.main) {
self.minimumDelay = minimumDelay
self.queue = queue
}
func throttle(_ block: @escaping () -> Void) {
// Cancel any existing work item if it has not yet executed
workItem.cancel()
// Re-assign workItem with the new block task, resetting the previousRun time when it executes
workItem = DispatchWorkItem() {
[weak self] in
self?.previousRun = Date()
block()
}
// If the time since the previous run is more than the required minimum delay
// => execute the workItem immediately
// else
// => delay the workItem execution by the minimum delay time
let delay = previousRun.timeIntervalSinceNow > minimumDelay ? 0 : minimumDelay
queue.asyncAfter(deadline: .now() + Double(delay), execute: workItem)
}
}
/// usage
let throttler = Throttler(minimumDelay: 0.5)
func frequentlyCalledMethod() {
// Throttling our computationally expensive task will ensure
// that it is only run once after 0.5 seconds have elapsed since last being requested,
// preventing excessive computation in the case that this method is called with high frequency
throttler.throttle {
computationallyExpensiveTask()
}
}
func computationallyExpensiveTask() {
}
/// altnative
import Foundation
import UIKit
public extension UIControl {
/// Default debounce delay for UIButton taps. Allows delay to be updated globally.
@objc static var debounceDelay: Double = 0.5
/// Debounces button taps with the specified delay.
@objc func debounce(delay: Double = UIControl.debounceDelay, siblings: [UIControl] = []) {
let buttons = [self] + siblings
buttons.forEach { $0.isEnabled = false }
let deadline = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: deadline) {
buttons.forEach { $0.isEnabled = true }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment