-
Notifications
You must be signed in to change notification settings - Fork 22
/
GCDTimer.swift
113 lines (90 loc) · 3.14 KB
/
GCDTimer.swift
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//
// GCDTimer.swift
// GCDTimer
//
// Created by Hemanta Sapkota on 4/06/2015.
// Copyright (c) 2023 Hemanta Sapkota. All rights reserved.
//
import Foundation
/**
* GCD Timer.
*/
open class GCDTimer {
// Swift 3 has removed support for dispatch_once. This class does the same thing ( roughly )
class Once {
private var _onceTracker = [String]()
// From: http://stackoverflow.com/questions/37886994/dispatch-once-in-swift-3
public func doIt(token: String, block:()->Void) {
objc_sync_enter(self); defer { objc_sync_exit(self) }
if _onceTracker.contains(token) {
return
}
_onceTracker.append(token)
block()
}
public func reset(token: String) {
if let tokenIndex = _onceTracker.firstIndex(of: token) {
_onceTracker.remove(at: tokenIndex)
}
}
}
/// A serial queue for processing our timer tasks
fileprivate static let gcdTimerQueue = DispatchQueue(label: "gcdTimerQueue", attributes: [])
/// Timer Source
public let timerSource = DispatchSource.makeTimerSource(flags: DispatchSource.TimerFlags(rawValue: UInt(0)), queue: GCDTimer.gcdTimerQueue)
/// Default internal: 1 second
fileprivate var interval:Double = 1
/// dispatch_once alternative
fileprivate let once = Once()
/// Event that is executed repeatedly
fileprivate var event: (() -> Void)!
open var Event: (() -> Void) {
get {
return event
}
set {
event = newValue
self.timerSource.schedule(deadline: DispatchTime.now(), repeating: DispatchTimeInterval.seconds(Int(interval)))
self.timerSource.setEventHandler {
self.event()
}
}
}
/**
Init a GCD timer in a paused state.
- parameter intervalInSecs: Time interval in seconds
- returns: self
*/
public init(intervalInSecs: Double) {
self.interval = intervalInSecs
}
/**
Start the timer.
*/
open func start() {
once.doIt(token: "com.laex.GCDTimer") { () in
self.timerSource.resume()
}
}
/**
Pause the timer.
*/
open func pause() {
timerSource.suspend()
once.reset(token: "com.laex.GCDTimer")
}
/**
Executes a block after a delay on the main thread.
*/
open class func delay(_ afterSecs: Double, block: @escaping ()->()) {
let delayTime = DispatchTime.now() + Double(Int64(afterSecs * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
DispatchQueue.main.asyncAfter(deadline: delayTime, execute: block)
}
/**
Executes a block after a delay on a specified queue.
*/
open class func delay(_ afterSecs: Double, queue: DispatchQueue, block: @escaping ()->()) {
let delayTime = DispatchTime.now() + Double(Int64(afterSecs * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
queue.asyncAfter(deadline: delayTime, execute: block)
}
}