├── DispatchTimer.playground ├── Contents.swift ├── Sources │ └── DispatchTimer.swift ├── contents.xcplayground ├── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── hurden.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── timeline.xctimeline ├── DispatchTimer.swift ├── Package.swift └── README.md /DispatchTimer.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | import Foundation 3 | import XCPlayground 4 | 5 | //: __DispatchTimer__ is a GCD-based NSTimer analogue that you can also __pause()__ / __resume()__ and set the finite number of invocations. 6 | 7 | XCPSetExecutionShouldContinueIndefinitely(true) 8 | let timerQueue:dispatch_queue_t = dispatch_queue_create("timerQueue", dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_BACKGROUND, 0)) 9 | 10 | //: Non-repeating or forever repeating timer 11 | 12 | let singleTimer = DispatchTimer.scheduledTimerWithTimeInterval(milliseconds: 1000, queue: timerQueue, repeats: false) { (timer:DispatchTimer) in 13 | 14 | NSLog("singleTimer: Fired") 15 | } 16 | 17 | sleep(2) 18 | //: Finite timer with multiple invocations(__fireCount__) 19 | 20 | let finiteTimer = DispatchTimer.scheduledTimerWithTimeInterval(milliseconds: 1000, queue: timerQueue, fireCount:10){ (timer:DispatchTimer) in 21 | NSLog("finiteTimer: Fired (remaining:\(timer.remainingFireCount))") 22 | } 23 | 24 | sleep(2) 25 | finiteTimer.pause() 26 | 27 | sleep(1) 28 | finiteTimer.resume() 29 | 30 | sleep(5) 31 | finiteTimer.invalidate() 32 | 33 | //: A bit more customizable factory method 34 | //: You can specify __startOffset__ to let timer start earlier. 35 | //: __tolerance__ specifies an allowable leeway for each invocation scheduling. 36 | //: (Please note the __tolerance__ of 0 does not guarantee precise sceduling. Usually each invocation will have a small deviation) 37 | 38 | let completionHandler = { (timer:DispatchTimer) in NSLog("anotherTimer: Done") } 39 | let anotherTimer = DispatchTimer.scheduledTimerWithTimeInterval(milliseconds: 1000, startOffset: -1000, tolerance: 0, queue: timerQueue, isFinite: true, fireCount: 10, userInfoº: nil, completionHandlerº: completionHandler) { (timer:DispatchTimer) in 40 | 41 | NSLog("anotherTimer: Fired (remaining:\(timer.remainingFireCount))") 42 | } 43 | 44 | 45 | //: Alternatively you can create a timer and start it later. 46 | //: Let's take a look at infinite timer which shows its invocation count 47 | let infiniteTimer = DispatchTimer.timerWithTimeInterval(milliseconds: 1000, queue: timerQueue, repeats: true) { (timer:DispatchTimer) in 48 | 49 | if var userInfo = timer.userInfoº as? UInt { 50 | NSLog("infiniteTimer: Invocation #\(userInfo)") 51 | userInfo++ 52 | timer.userInfoº = userInfo 53 | } 54 | } 55 | 56 | infiniteTimer.userInfoº = UInt(0) 57 | infiniteTimer.start() 58 | 59 | -------------------------------------------------------------------------------- /DispatchTimer.playground/Sources/DispatchTimer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DispatchTimer.swift 3 | // AmbientUPNP 4 | // 5 | // Created by Taras Vozniuk on 7/11/15. 6 | // Copyright (c) 2015 ambientlight. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class DispatchTimer: Equatable { 12 | 13 | public enum Status { 14 | case NotStarted 15 | case Active 16 | case Paused 17 | case Done 18 | case Invalidated 19 | } 20 | 21 | private var _timerSource:dispatch_source_t 22 | private var _isInvalidating:Bool = false 23 | //either startDate or lastFire or lastResume date 24 | private var _lastActiveDateº:NSDate? 25 | private var _elapsedAccumulatedTime: Double = Double(0) 26 | 27 | 28 | //MARK: PROPERTIES 29 | 30 | public private(set) var remainingFireCount:UInt 31 | public private(set) var status:DispatchTimer.Status = .NotStarted 32 | public private(set) var startDateº:NSDate? 33 | 34 | public let queue:dispatch_queue_t 35 | public let isFinite:Bool 36 | public let fireCount:UInt 37 | public let interval:UInt 38 | public let invocationBlock:(timer:DispatchTimer) -> Void 39 | 40 | public var completionHandlerº:((timer:DispatchTimer) -> Void)? 41 | public var userInfoº:Any? 42 | 43 | public var valid:Bool { return (self.status != .Done || self.status != .Invalidated) } 44 | public var started:Bool { return (self.status != .NotStarted) } 45 | public var startAbsoluteTimeº:Double? { return (startDateº != nil) ? self.startDateº!.timeIntervalSince1970 : nil } 46 | 47 | 48 | 49 | //all parameters are in milliseconds 50 | private func _setupTimerSource(timeInterval:UInt, startOffset:UInt, leeway: UInt) { 51 | 52 | dispatch_source_set_timer(_timerSource, dispatch_time(DISPATCH_TIME_NOW, Int64(UInt64(startOffset) * NSEC_PER_MSEC)), UInt64(timeInterval) * NSEC_PER_MSEC, UInt64(leeway) * NSEC_PER_MSEC) 53 | dispatch_source_set_event_handler(_timerSource) { 54 | 55 | self._elapsedAccumulatedTime = 0 56 | self._lastActiveDateº = NSDate() 57 | 58 | self.invocationBlock(timer: self) 59 | if(self.isFinite){ 60 | 61 | self.remainingFireCount-- 62 | if(self.remainingFireCount == 0){ 63 | dispatch_source_cancel(self._timerSource) 64 | } 65 | } 66 | } 67 | 68 | dispatch_source_set_cancel_handler(_timerSource){ 69 | if(self._isInvalidating){ 70 | self.status = .Invalidated 71 | self._isInvalidating = false 72 | } else { 73 | self.status = .Done 74 | } 75 | 76 | self.completionHandlerº?(timer: self) 77 | } 78 | } 79 | 80 | //MARK: 81 | 82 | public init(milliseconds:UInt, startOffset:Int, tolerance:UInt, queue: dispatch_queue_t, isFinite:Bool, fireCount:UInt, userInfoº:Any?, completionHandlerº:((timer:DispatchTimer) -> Void)?,invocationBlock: (timer:DispatchTimer) -> Void) { 83 | 84 | self.queue = queue 85 | 86 | self.userInfoº = userInfoº 87 | self.isFinite = isFinite 88 | self.fireCount = fireCount; 89 | self.remainingFireCount = self.fireCount 90 | 91 | self.userInfoº = userInfoº 92 | self.completionHandlerº = completionHandlerº 93 | self.invocationBlock = invocationBlock 94 | 95 | self.interval = milliseconds 96 | _timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue) 97 | 98 | 99 | let offset:Int = ( (startOffset < 0) && (abs(startOffset) > Int(self.interval)) ) ? -Int(self.interval) : startOffset 100 | _setupTimerSource(self.interval, startOffset: UInt( Int(self.interval) + offset), leeway: tolerance) 101 | } 102 | 103 | 104 | public class func timerWithTimeInterval(milliseconds milliseconds: UInt, queue: dispatch_queue_t, repeats: Bool, invocationBlock: (timer:DispatchTimer) -> Void) -> DispatchTimer { 105 | 106 | 107 | let timer = DispatchTimer(milliseconds: milliseconds, startOffset: 0, tolerance: 0, queue: queue, isFinite: !repeats, fireCount: (repeats) ? 0 : 1, userInfoº: nil, completionHandlerº:nil, invocationBlock: invocationBlock) 108 | return timer 109 | } 110 | 111 | public class func timerWithTimeInterval(milliseconds milliseconds: UInt, queue: dispatch_queue_t, fireCount: UInt, invocationBlock: (timer:DispatchTimer) -> Void) -> DispatchTimer { 112 | 113 | let timer = DispatchTimer(milliseconds: milliseconds, startOffset: 0, tolerance: 0, queue: queue, isFinite: true, fireCount: fireCount, userInfoº: nil, completionHandlerº:nil, invocationBlock: invocationBlock) 114 | return timer 115 | } 116 | 117 | 118 | 119 | 120 | public class func scheduledTimerWithTimeInterval(milliseconds milliseconds: UInt, queue: dispatch_queue_t, repeats: Bool, invocationBlock: (timer:DispatchTimer) -> Void) -> DispatchTimer { 121 | 122 | let timer = DispatchTimer(milliseconds: milliseconds, startOffset: 0, tolerance: 0, queue: queue, isFinite: !repeats, fireCount: (repeats) ? 0 : 1, userInfoº: nil, completionHandlerº:nil, invocationBlock: invocationBlock) 123 | timer.start() 124 | return timer 125 | } 126 | 127 | public class func scheduledTimerWithTimeInterval(milliseconds milliseconds: UInt, queue: dispatch_queue_t, fireCount: UInt, invocationBlock: (timer:DispatchTimer) -> Void) -> DispatchTimer { 128 | 129 | let timer = DispatchTimer(milliseconds: milliseconds, startOffset: 0, tolerance: 0, queue: queue, isFinite: true, fireCount: fireCount, userInfoº: nil, completionHandlerº:nil, invocationBlock: invocationBlock) 130 | timer.start() 131 | return timer 132 | } 133 | 134 | public class func scheduledTimerWithTimeInterval(milliseconds milliseconds:UInt, startOffset:Int, tolerance:UInt, queue: dispatch_queue_t, isFinite:Bool, fireCount:UInt, userInfoº:Any?, completionHandlerº:((timer:DispatchTimer) -> Void)?, invocationBlock: (timer:DispatchTimer) -> Void) -> DispatchTimer { 135 | 136 | let timer = DispatchTimer(milliseconds: milliseconds, startOffset: startOffset, tolerance: tolerance, queue: queue, isFinite: isFinite, fireCount: fireCount, userInfoº: userInfoº, completionHandlerº:completionHandlerº, invocationBlock: invocationBlock) 137 | timer.start() 138 | return timer 139 | } 140 | 141 | //MARK: METHODS 142 | 143 | public func start(){ 144 | 145 | if (!self.started){ 146 | dispatch_resume(_timerSource) 147 | 148 | self.startDateº = NSDate() 149 | _lastActiveDateº = self.startDateº 150 | self.status = .Active 151 | } 152 | } 153 | 154 | public func pause(){ 155 | 156 | if (self.status == .Active){ 157 | 158 | dispatch_source_set_cancel_handler(_timerSource){ } 159 | dispatch_source_cancel(_timerSource) 160 | self.status = .Paused 161 | 162 | let pauseDate = NSDate() 163 | 164 | _elapsedAccumulatedTime += (pauseDate.timeIntervalSince1970 - _lastActiveDateº!.timeIntervalSince1970) * 1000 165 | 166 | //NSLog("%ld milliseconds elapsed", UInt(_elapsedAccumulatedTime)) 167 | } 168 | } 169 | 170 | public func resume(){ 171 | 172 | if (self.status == .Paused){ 173 | 174 | //NSLog("%ld milliseconds left till fire", self.interval - UInt(_elapsedAccumulatedTime)) 175 | 176 | _timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue) 177 | _setupTimerSource(self.interval, startOffset: self.interval - UInt(_elapsedAccumulatedTime), leeway: 0) 178 | dispatch_resume(_timerSource) 179 | 180 | _lastActiveDateº = NSDate() 181 | self.status = .Active 182 | } 183 | } 184 | 185 | public func invalidate(handlerº:((timer:DispatchTimer)-> Void)? = nil){ 186 | 187 | _isInvalidating = true; 188 | 189 | // reassigning completionHandler if has been passed(non-nil) 190 | if let handler = completionHandlerº { 191 | self.completionHandlerº = handler 192 | } 193 | 194 | dispatch_source_cancel(_timerSource) 195 | } 196 | } 197 | 198 | //MARK: Equatable 199 | public func ==(lhs: DispatchTimer, rhs: DispatchTimer) -> Bool { 200 | return (lhs._timerSource === rhs._timerSource) 201 | } 202 | -------------------------------------------------------------------------------- /DispatchTimer.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /DispatchTimer.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DispatchTimer.playground/playground.xcworkspace/xcuserdata/hurden.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ambientlight/DispatchTimer/029803d599d1190e3c3f263ec99dfe0e1c5ad08f/DispatchTimer.playground/playground.xcworkspace/xcuserdata/hurden.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /DispatchTimer.playground/timeline.xctimeline: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /DispatchTimer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DispatchTimer.swift 3 | // AmbientUPNP 4 | // 5 | // Created by Taras Vozniuk on 7/11/15. 6 | // Copyright (c) 2015 ambientlight. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class DispatchTimer: Equatable { 12 | 13 | public enum Status { 14 | case NotStarted 15 | case Active 16 | case Paused 17 | case Done 18 | case Invalidated 19 | } 20 | 21 | private var _timerSource:dispatch_source_t 22 | private var _isInvalidating:Bool = false 23 | //either startDate or lastFire or lastResume date 24 | private var _lastActiveDateº:NSDate? 25 | private var _elapsedAccumulatedTime: Double = Double(0) 26 | 27 | 28 | //MARK: PROPERTIES 29 | 30 | public private(set) var remainingFireCount:UInt 31 | public private(set) var status:DispatchTimer.Status = .NotStarted 32 | public private(set) var startDateº:NSDate? 33 | 34 | public let queue:dispatch_queue_t 35 | public let isFinite:Bool 36 | public let fireCount:UInt 37 | public let interval:UInt 38 | public let invocationBlock:(timer:DispatchTimer) -> Void 39 | 40 | public var completionHandlerº:((timer:DispatchTimer) -> Void)? 41 | public var userInfoº:Any? 42 | 43 | public var valid:Bool { return (self.status != .Done || self.status != .Invalidated) } 44 | public var started:Bool { return (self.status != .NotStarted) } 45 | public var startAbsoluteTimeº:Double? { return (startDateº != nil) ? self.startDateº!.timeIntervalSince1970 : nil } 46 | 47 | 48 | 49 | //all parameters are in milliseconds 50 | private func _setupTimerSource(timeInterval:UInt, startOffset:UInt, leeway: UInt) { 51 | 52 | dispatch_source_set_timer(_timerSource, dispatch_time(DISPATCH_TIME_NOW, Int64(UInt64(startOffset) * NSEC_PER_MSEC)), UInt64(timeInterval) * NSEC_PER_MSEC, UInt64(leeway) * NSEC_PER_MSEC) 53 | dispatch_source_set_event_handler(_timerSource) { 54 | 55 | self._elapsedAccumulatedTime = 0 56 | self._lastActiveDateº = NSDate() 57 | 58 | self.invocationBlock(timer: self) 59 | if(self.isFinite){ 60 | 61 | self.remainingFireCount -= 1 62 | if(self.remainingFireCount == 0){ 63 | dispatch_source_cancel(self._timerSource) 64 | } 65 | } 66 | } 67 | 68 | dispatch_source_set_cancel_handler(_timerSource){ 69 | if(self._isInvalidating){ 70 | self.status = .Invalidated 71 | self._isInvalidating = false 72 | } else { 73 | self.status = .Done 74 | } 75 | 76 | self.completionHandlerº?(timer: self) 77 | } 78 | } 79 | 80 | //MARK: 81 | 82 | public init(milliseconds:UInt, startOffset:Int, tolerance:UInt, queue: dispatch_queue_t, isFinite:Bool, fireCount:UInt, userInfoº:Any?, completionHandlerº:((timer:DispatchTimer) -> Void)?,invocationBlock: (timer:DispatchTimer) -> Void) { 83 | 84 | self.queue = queue 85 | 86 | self.userInfoº = userInfoº 87 | self.isFinite = isFinite 88 | self.fireCount = fireCount; 89 | self.remainingFireCount = self.fireCount 90 | 91 | self.userInfoº = userInfoº 92 | self.completionHandlerº = completionHandlerº 93 | self.invocationBlock = invocationBlock 94 | 95 | self.interval = milliseconds 96 | _timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue) 97 | 98 | 99 | let offset:Int = ( (startOffset < 0) && (abs(startOffset) > Int(self.interval)) ) ? -Int(self.interval) : startOffset 100 | _setupTimerSource(self.interval, startOffset: UInt( Int(self.interval) + offset), leeway: tolerance) 101 | } 102 | 103 | 104 | public class func timerWithTimeInterval(milliseconds milliseconds: UInt, queue: dispatch_queue_t, repeats: Bool, invocationBlock: (timer:DispatchTimer) -> Void) -> DispatchTimer { 105 | 106 | 107 | let timer = DispatchTimer(milliseconds: milliseconds, startOffset: 0, tolerance: 0, queue: queue, isFinite: !repeats, fireCount: (repeats) ? 0 : 1, userInfoº: nil, completionHandlerº:nil, invocationBlock: invocationBlock) 108 | return timer 109 | } 110 | 111 | public class func timerWithTimeInterval(milliseconds milliseconds: UInt, queue: dispatch_queue_t, fireCount: UInt, invocationBlock: (timer:DispatchTimer) -> Void) -> DispatchTimer { 112 | 113 | let timer = DispatchTimer(milliseconds: milliseconds, startOffset: 0, tolerance: 0, queue: queue, isFinite: true, fireCount: fireCount, userInfoº: nil, completionHandlerº:nil, invocationBlock: invocationBlock) 114 | return timer 115 | } 116 | 117 | 118 | 119 | 120 | public class func scheduledTimerWithTimeInterval(milliseconds milliseconds: UInt, queue: dispatch_queue_t, repeats: Bool, invocationBlock: (timer:DispatchTimer) -> Void) -> DispatchTimer { 121 | 122 | let timer = DispatchTimer(milliseconds: milliseconds, startOffset: 0, tolerance: 0, queue: queue, isFinite: !repeats, fireCount: (repeats) ? 0 : 1, userInfoº: nil, completionHandlerº:nil, invocationBlock: invocationBlock) 123 | timer.start() 124 | return timer 125 | } 126 | 127 | public class func scheduledTimerWithTimeInterval(milliseconds milliseconds: UInt, queue: dispatch_queue_t, fireCount: UInt, invocationBlock: (timer:DispatchTimer) -> Void) -> DispatchTimer { 128 | 129 | let timer = DispatchTimer(milliseconds: milliseconds, startOffset: 0, tolerance: 0, queue: queue, isFinite: true, fireCount: fireCount, userInfoº: nil, completionHandlerº:nil, invocationBlock: invocationBlock) 130 | timer.start() 131 | return timer 132 | } 133 | 134 | public class func scheduledTimerWithTimeInterval(milliseconds milliseconds:UInt, startOffset:Int, tolerance:UInt, queue: dispatch_queue_t, isFinite:Bool, fireCount:UInt, userInfoº:Any?, completionHandlerº:((timer:DispatchTimer) -> Void)?, invocationBlock: (timer:DispatchTimer) -> Void) -> DispatchTimer { 135 | 136 | let timer = DispatchTimer(milliseconds: milliseconds, startOffset: startOffset, tolerance: tolerance, queue: queue, isFinite: isFinite, fireCount: fireCount, userInfoº: userInfoº, completionHandlerº:completionHandlerº, invocationBlock: invocationBlock) 137 | timer.start() 138 | return timer 139 | } 140 | 141 | //MARK: METHODS 142 | 143 | public func start(){ 144 | 145 | if (!self.started){ 146 | dispatch_resume(_timerSource) 147 | 148 | self.startDateº = NSDate() 149 | _lastActiveDateº = self.startDateº 150 | self.status = .Active 151 | } 152 | } 153 | 154 | public func pause(){ 155 | 156 | if (self.status == .Active){ 157 | 158 | dispatch_source_set_cancel_handler(_timerSource){ } 159 | dispatch_source_cancel(_timerSource) 160 | self.status = .Paused 161 | 162 | let pauseDate = NSDate() 163 | 164 | _elapsedAccumulatedTime += (pauseDate.timeIntervalSince1970 - _lastActiveDateº!.timeIntervalSince1970) * 1000 165 | 166 | //NSLog("%ld milliseconds elapsed", UInt(_elapsedAccumulatedTime)) 167 | } 168 | } 169 | 170 | public func resume(){ 171 | 172 | if (self.status == .Paused){ 173 | 174 | //NSLog("%ld milliseconds left till fire", self.interval - UInt(_elapsedAccumulatedTime)) 175 | 176 | _timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue) 177 | _setupTimerSource(self.interval, startOffset: self.interval - UInt(_elapsedAccumulatedTime), leeway: 0) 178 | dispatch_resume(_timerSource) 179 | 180 | _lastActiveDateº = NSDate() 181 | self.status = .Active 182 | } 183 | } 184 | 185 | public func invalidate(handlerº:((timer:DispatchTimer)-> Void)? = nil){ 186 | 187 | _isInvalidating = true; 188 | 189 | // reassigning completionHandler if has been passed(non-nil) 190 | if let handler = completionHandlerº { 191 | self.completionHandlerº = handler 192 | } 193 | 194 | dispatch_source_cancel(_timerSource) 195 | } 196 | } 197 | 198 | //MARK: Equatable 199 | public func ==(lhs: DispatchTimer, rhs: DispatchTimer) -> Bool { 200 | return (lhs._timerSource === rhs._timerSource) 201 | } 202 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | import PackageDescription 2 | 3 | let package = Package(name:"DispatchTimer") 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##DispatchTimer 2 | __DispatchTimer__ is a GCD-based NSTimer analogue that you can also __pause__/__resume__ and set a finite number of invocations. 3 | 4 | 5 | 6 | ##Examples 7 | Please take a look at __DispatchTimer.playground__. 8 | 9 | ####Non-repeating or Infinite timer 10 | 11 | ```swift 12 | let timerQueue:dispatch_queue_t = dispatch_queue_create("timerQueue", dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_BACKGROUND, 0)) 13 | 14 | let singleTimer = DispatchTimer.scheduledTimerWithTimeInterval(milliseconds: 1000, queue: timerQueue, repeats: false) { (timer:DispatchTimer) in 15 | NSLog("singleTimer: Fired") 16 | } 17 | ``` 18 | 19 | ####Finite timer(multiple # of invocations) 20 | ```swift 21 | let timerQueue:dispatch_queue_t = dispatch_queue_create("timerQueue", dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_BACKGROUND, 0)) 22 | 23 | let finiteTimer = DispatchTimer.scheduledTimerWithTimeInterval(milliseconds: 1000, queue: timerQueue, fireCount:10){ (timer:DispatchTimer) in 24 | NSLog("finiteTimer: Fired (remaining:\(timer.remainingFireCount))") 25 | } 26 | 27 | sleep(2) 28 | finiteTimer.pause() 29 | 30 | sleep(1) 31 | finiteTimer.resume() 32 | 33 | sleep(5) 34 | finiteTimer.invalidate() 35 | 36 | ``` 37 | 38 | ####More examples 39 | In a bit longer factory method you can specify __startOffset__ to let timer start earlier. 40 | __tolerance__ specifies an allowable leeway for each invocation scheduling. 41 | (Please note the __tolerance__ of 0 does not guarantee precise sceduling. Usually each invocation will have a small deviation) 42 | 43 | ```swift 44 | let timerQueue:dispatch_queue_t = dispatch_queue_create("timerQueue", 45 | 46 | let completionHandler = { (timer:DispatchTimer) in NSLog("anotherTimer: Done") } 47 | let anotherTimer = DispatchTimer.scheduledTimerWithTimeInterval(milliseconds: 1000, startOffset: -1000, tolerance: 0, queue: timerQueue, isFinite: true, fireCount: 10, userInfoº: nil, completionHandlerº: completionHandler) { (timer:DispatchTimer) in 48 | NSLog("anotherTimer: Fired (remaining:\(timer.remainingFireCount))") 49 | } 50 | ``` 51 | 52 | Alternatively you can also create a timer and start it later. 53 | Lets take a look at the infinite timer which shows its invocation count 54 | 55 | ```swift 56 | let timerQueue:dispatch_queue_t = dispatch_queue_create("timerQueue", 57 | 58 | let infiniteTimer = DispatchTimer.timerWithTimeInterval(milliseconds: 1000, queue: timerQueue, repeats: true) { (timer:DispatchTimer) in 59 | if var userInfo = timer.userInfoº as? UInt { 60 | NSLog("infiniteTimer: Invocation #\(userInfo)") 61 | userInfo++ 62 | timer.userInfoº = userInfo 63 | } 64 | } 65 | 66 | infiniteTimer.userInfoº = UInt(0) 67 | infiniteTimer.start() 68 | ``` 69 | ##Requirement 70 | * Swift 2.0 (Xcode 7+) 71 | * iOS 7+ --------------------------------------------------------------------------------