How to do throttle and debounce using DispatchWorkItem in Swift

Issue #376

https://github.com/onmyway133/Omnia/blob/master/Sources/Shared/Debouncer.swift

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import Foundation

public class Debouncer {
private let delay: TimeInterval
private var workItem: DispatchWorkItem?

public init(delay: TimeInterval) {
self.delay = delay
}

/// Trigger the action after some delay
public func run(action: @escaping () -> Void) {
workItem?.cancel()
workItem = DispatchWorkItem(block: action)
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: workItem!)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import XCTest

class DebouncerTests: XCTestCase {

func testDebounce() {
let expectation = self.expectation(description: #function)
let debouncer = Debouncer(delay: 0.5)
var value = 0

debouncer.run(action: {
value = 1
})

debouncer.run(action: {
value = 2
})

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2, execute: {
debouncer.run(action: {
value = 3
})
})

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.71, execute: {
XCTAssertEqual(value, 3)
expectation.fulfill()
})

wait(for: [expectation], timeout: 1.2)
}
}

Comments