-
Star
(109)
You must be signed in to star a gist -
Fork
(3)
You must be signed in to fork a gist
extension NSTimer { | |
/** | |
Creates and schedules a one-time `NSTimer` instance. | |
- Parameters: | |
- delay: The delay before execution. | |
- handler: A closure to execute after `delay`. | |
- Returns: The newly-created `NSTimer` instance. | |
*/ | |
class func schedule(delay delay: NSTimeInterval, handler: NSTimer! -> Void) -> NSTimer { | |
let fireDate = delay + CFAbsoluteTimeGetCurrent() | |
let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, 0, 0, 0, handler) | |
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes) | |
return timer | |
} | |
/** | |
Creates and schedules a repeating `NSTimer` instance. | |
- Parameters: | |
- repeatInterval: The interval (in seconds) between each execution of | |
`handler`. Note that individual calls may be delayed; subsequent calls | |
to `handler` will be based on the time the timer was created. | |
- handler: A closure to execute at each `repeatInterval`. | |
- Returns: The newly-created `NSTimer` instance. | |
*/ | |
class func schedule(repeatInterval interval: NSTimeInterval, handler: NSTimer! -> Void) -> NSTimer { | |
let fireDate = interval + CFAbsoluteTimeGetCurrent() | |
let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, interval, 0, 0, handler) | |
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes) | |
return timer | |
} | |
} | |
// Usage: | |
var count = 0 | |
NSTimer.schedule(repeatInterval: 1) { timer in | |
print(++count) | |
if count >= 10 { | |
timer.invalidate() | |
} | |
} | |
NSTimer.schedule(delay: 5) { timer in | |
print("5 seconds") | |
} |
Great suggestion, thanks! Makes the wrapper around the closure completely unnecessary.
Just a minor styling addition, I think scheduledTimerWithTimeInterval
is too long for a method name and could be easily replaced here by schedule(interval: repeats)
.
So I'd prefer using it like NSTimer.schedule(interval: 1, repeats: true)
which is more concise, yet as clear. (more thoughts on Swift method naming here)
@rinatkhanov, I like that idea too. I've split the original method into NSTimer.schedule(delay:handler:)
and NSTimer.schedule(repeatInterval:handler:)
.
how can I use this extension to reset and restart the timer every 20 seconds? The method will be inserted in a UIButton action. Thanks!
This is what I'm running for Swift 3.0:
extension Timer {
/**
Creates and schedules a one-time `NSTimer` instance.
:param: delay The delay before execution.
:param: handler A closure to execute after `delay`.
:returns: The newly-created `NSTimer` instance.
*/
class func schedule(delay: TimeInterval, handler: @escaping (Timer?) -> Void) -> Timer {
let fireDate = delay + CFAbsoluteTimeGetCurrent()
let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, 0, 0, 0, handler)!
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes)
return timer
}
/**
Creates and schedules a repeating `NSTimer` instance.
:param: repeatInterval The interval between each execution of `handler`. Note that individual calls may be delayed; subsequent calls to `handler` will be based on the time the `NSTimer` was created.
:param: handler A closure to execute after `delay`.
:returns: The newly-created `NSTimer` instance.
*/
class func schedule(repeatInterval interval: TimeInterval, handler: @escaping (Timer?) -> Void) -> Timer {
let fireDate = interval + CFAbsoluteTimeGetCurrent()
let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, interval, 0, 0, handler)!
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes)
return timer
}
}
Also from iOS 10, there is a native method on Timer
that does this: Timer.scheduledTimer(withTimeInterval: TimeInterval, repeats: Bool, block: (Timer) -> Void)
Consider using
CFRunLoopTimerCreateWithHandler
, which toll-free bridges toNSTimer
.