Last active
June 11, 2020 09:10
-
-
Save ostholz/5e86319645af93127e5d1d51719d651a to your computer and use it in GitHub Desktop.
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
// 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