You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
5.5 KiB

6 years ago
  1. //
  2. // SwiftyTimer
  3. //
  4. // Copyright (c) 2015-2016 Radosław Pietruszewski
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in all
  14. // copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. // SOFTWARE.
  23. //
  24. import Foundation
  25. extension Timer {
  26. // MARK: Schedule timers
  27. /// Create and schedule a timer that will call `block` once after the specified time.
  28. @discardableResult
  29. public class func after(_ interval: TimeInterval, _ block: @escaping () -> Void) -> Timer {
  30. let timer = Timer.new(after: interval, block)
  31. timer.start()
  32. return timer
  33. }
  34. /// Create and schedule a timer that will call `block` repeatedly in specified time intervals.
  35. @discardableResult
  36. public class func every(_ interval: TimeInterval, _ block: @escaping () -> Void) -> Timer {
  37. let timer = Timer.new(every: interval, block)
  38. timer.start()
  39. return timer
  40. }
  41. /// Create and schedule a timer that will call `block` repeatedly in specified time intervals.
  42. /// (This variant also passes the timer instance to the block)
  43. @nonobjc @discardableResult
  44. public class func every(_ interval: TimeInterval, _ block: @escaping (Timer) -> Void) -> Timer {
  45. let timer = Timer.new(every: interval, block)
  46. timer.start()
  47. return timer
  48. }
  49. // MARK: Create timers without scheduling
  50. /// Create a timer that will call `block` once after the specified time.
  51. ///
  52. /// - Note: The timer won't fire until it's scheduled on the run loop.
  53. /// Use `NSTimer.after` to create and schedule a timer in one step.
  54. /// - Note: The `new` class function is a workaround for a crashing bug when using convenience initializers (rdar://18720947)
  55. public class func new(after interval: TimeInterval, _ block: @escaping () -> Void) -> Timer {
  56. return CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + interval, 0, 0, 0) { _ in
  57. block()
  58. }
  59. }
  60. /// Create a timer that will call `block` repeatedly in specified time intervals.
  61. ///
  62. /// - Note: The timer won't fire until it's scheduled on the run loop.
  63. /// Use `NSTimer.every` to create and schedule a timer in one step.
  64. /// - Note: The `new` class function is a workaround for a crashing bug when using convenience initializers (rdar://18720947)
  65. public class func new(every interval: TimeInterval, _ block: @escaping () -> Void) -> Timer {
  66. return CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + interval, interval, 0, 0) { _ in
  67. block()
  68. }
  69. }
  70. /// Create a timer that will call `block` repeatedly in specified time intervals.
  71. /// (This variant also passes the timer instance to the block)
  72. ///
  73. /// - Note: The timer won't fire until it's scheduled on the run loop.
  74. /// Use `NSTimer.every` to create and schedule a timer in one step.
  75. /// - Note: The `new` class function is a workaround for a crashing bug when using convenience initializers (rdar://18720947)
  76. @nonobjc public class func new(every interval: TimeInterval, _ block: @escaping (Timer) -> Void) -> Timer {
  77. var timer: Timer!
  78. timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + interval, interval, 0, 0) { _ in
  79. block(timer)
  80. }
  81. return timer
  82. }
  83. // MARK: Manual scheduling
  84. /// Schedule this timer on the run loop
  85. ///
  86. /// By default, the timer is scheduled on the current run loop for the default mode.
  87. /// Specify `runLoop` or `modes` to override these defaults.
  88. public func start(runLoop: RunLoop = .current, modes: RunLoop.Mode...) {
  89. let modes = modes.isEmpty ? [.default] : modes
  90. for mode in modes {
  91. runLoop.add(self, forMode: mode)
  92. }
  93. }
  94. }
  95. // MARK: - Time extensions
  96. extension Double {
  97. public var millisecond: TimeInterval { return self / 1000 }
  98. public var milliseconds: TimeInterval { return self / 1000 }
  99. public var ms: TimeInterval { return self / 1000 }
  100. public var second: TimeInterval { return self }
  101. public var seconds: TimeInterval { return self }
  102. public var minute: TimeInterval { return self * 60 }
  103. public var minutes: TimeInterval { return self * 60 }
  104. public var hour: TimeInterval { return self * 3600 }
  105. public var hours: TimeInterval { return self * 3600 }
  106. public var day: TimeInterval { return self * 3600 * 24 }
  107. public var days: TimeInterval { return self * 3600 * 24 }
  108. }