Last active
September 2, 2016 17:12
-
-
Save JadenGeller/583214332eda1829b203fe618e0c8251 to your computer and use it in GitHub Desktop.
Clock Controller
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
// Controller that evokes its callback every minute | |
class ClockController { | |
private let minuteCallback: NSDate -> () | |
init(minuteCallback: NSDate -> ()) { | |
self.minuteCallback = minuteCallback | |
callbackAndReschedule() | |
} | |
func callbackAndReschedule() { | |
let now = NSDate() | |
minuteCallback(now) | |
schedule(nextMinuteAfter: now) | |
} | |
func schedule(nextMinuteAfter date: NSDate) { | |
var spec = timespec(tv_sec: Int(date.timeIntervalSince1970), tv_nsec: 0) | |
// Adjust the time for exactly on the next minute | |
spec.tv_sec -= spec.tv_sec % 60 | |
spec.tv_sec += 60 | |
let time = withUnsafePointer(&spec) { dispatch_walltime($0, 0) } | |
dispatch_after(time, dispatch_get_main_queue()) { [weak self] in | |
self?.callbackAndReschedule() | |
} | |
} | |
} | |
let controller = ClockController { date in | |
print("Hi \(date)") // Will run on init and on the minute, every minute thereafter | |
} | |
// If the object is deallocated, the callback will no longer be called. | |
// So keep a strong reference to the object, and cancel it by deallocating it. | |
dispatch_main() |
So why not just use an NSTimer?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note that this doesn't handle changes to the system clock. We can handle that by adding an observer to the
NSSystemClockDidChangeNotification
notification ininit
(and removing the observer indealloc
). When we receive a notification, we should cancel our last dispatch and schedule a new one. Note thatdispatch_after
does not support canceling blocks, so you'll have to use the lower level dispatch source API.