SwiftTimer.swift 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. //
  2. // SwiftTimer.swift
  3. // SwiftTimer
  4. //
  5. // Created by mangofang on 16/8/23.
  6. //
  7. //
  8. import Foundation
  9. public class SwiftTimer {
  10. private let internalTimer: DispatchSourceTimer
  11. private var isRunning = false
  12. public let repeats: Bool
  13. public typealias SwiftTimerHandler = (SwiftTimer) -> Void
  14. private var handler: SwiftTimerHandler
  15. public init(interval: DispatchTimeInterval, repeats: Bool = false, queue: DispatchQueue = .main , handler: @escaping SwiftTimerHandler) {
  16. self.handler = handler
  17. self.repeats = repeats
  18. internalTimer = DispatchSource.makeTimerSource(queue: queue)
  19. internalTimer.setEventHandler { [weak self] in
  20. if let strongSelf = self {
  21. handler(strongSelf)
  22. }
  23. }
  24. if repeats {
  25. internalTimer.schedule(deadline: .now() + interval, repeating: interval)
  26. } else {
  27. internalTimer.schedule(deadline: .now() + interval)
  28. }
  29. }
  30. public static func repeaticTimer(interval: DispatchTimeInterval, queue: DispatchQueue = .main , handler: @escaping SwiftTimerHandler ) -> SwiftTimer {
  31. return SwiftTimer(interval: interval, repeats: true, queue: queue, handler: handler)
  32. }
  33. deinit {
  34. if !self.isRunning {
  35. internalTimer.resume()
  36. }
  37. }
  38. //You can use this method to fire a repeating timer without interrupting its regular firing schedule. If the timer is non-repeating, it is automatically invalidated after firing, even if its scheduled fire date has not arrived.
  39. public func fire() {
  40. if repeats {
  41. handler(self)
  42. } else {
  43. handler(self)
  44. internalTimer.cancel()
  45. }
  46. }
  47. public func start() {
  48. if !isRunning {
  49. internalTimer.resume()
  50. isRunning = true
  51. }
  52. }
  53. public func suspend() {
  54. if isRunning {
  55. internalTimer.suspend()
  56. isRunning = false
  57. }
  58. }
  59. public func rescheduleRepeating(interval: DispatchTimeInterval) {
  60. if repeats {
  61. internalTimer.schedule(deadline: .now() + interval, repeating: interval)
  62. }
  63. }
  64. public func rescheduleHandler(handler: @escaping SwiftTimerHandler) {
  65. self.handler = handler
  66. internalTimer.setEventHandler { [weak self] in
  67. if let strongSelf = self {
  68. handler(strongSelf)
  69. }
  70. }
  71. }
  72. }
  73. //MARK: Throttle
  74. public extension SwiftTimer {
  75. private static var timers = [String:DispatchSourceTimer]()
  76. public static func throttle(interval: DispatchTimeInterval, identifier: String, queue: DispatchQueue = .main , handler: @escaping () -> Void ) {
  77. if let previousTimer = timers[identifier] {
  78. previousTimer.cancel()
  79. timers.removeValue(forKey: identifier)
  80. }
  81. let timer = DispatchSource.makeTimerSource(queue: queue)
  82. timers[identifier] = timer
  83. timer.schedule(deadline: .now() + interval)
  84. timer.setEventHandler {
  85. handler()
  86. timer.cancel()
  87. timers.removeValue(forKey: identifier)
  88. }
  89. timer.resume()
  90. }
  91. public static func cancelThrottlingTimer(identifier: String) {
  92. if let previousTimer = timers[identifier] {
  93. previousTimer.cancel()
  94. timers.removeValue(forKey: identifier)
  95. }
  96. }
  97. }
  98. //MARK: Count Down
  99. public class SwiftCountDownTimer {
  100. private let internalTimer: SwiftTimer
  101. private var leftTimes: Int
  102. private let originalTimes: Int
  103. private let handler: (SwiftCountDownTimer, _ leftTimes: Int) -> Void
  104. public init(interval: DispatchTimeInterval, times: Int,queue: DispatchQueue = .main , handler: @escaping (SwiftCountDownTimer, _ leftTimes: Int) -> Void ) {
  105. self.leftTimes = times
  106. self.originalTimes = times
  107. self.handler = handler
  108. self.internalTimer = SwiftTimer.repeaticTimer(interval: interval, queue: queue, handler: { _ in
  109. })
  110. self.internalTimer.rescheduleHandler { [weak self] swiftTimer in
  111. if let strongSelf = self {
  112. if strongSelf.leftTimes > 0 {
  113. strongSelf.leftTimes = strongSelf.leftTimes - 1
  114. strongSelf.handler(strongSelf, strongSelf.leftTimes)
  115. } else {
  116. strongSelf.internalTimer.suspend()
  117. }
  118. }
  119. }
  120. }
  121. public func start() {
  122. self.internalTimer.start()
  123. }
  124. public func suspend() {
  125. self.internalTimer.suspend()
  126. }
  127. public func reCountDown() {
  128. self.leftTimes = self.originalTimes
  129. }
  130. }
  131. public extension DispatchTimeInterval {
  132. public static func fromSeconds(_ seconds: Double) -> DispatchTimeInterval {
  133. return .milliseconds(Int(seconds * 1000))
  134. }
  135. }