问题
I'm trying to make a nice timer using Swift and GCD. I find lots of blogs and even an entry in Matt Neuburg's book. I used the latter to put together my own variant in a playground:
import Foundation
struct Timer {
private var queue = dispatch_queue_create("timer", nil)
private var source: dispatch_source_t
var tick:()->() = {} {
didSet {
self.update()
}
}
var rate:Double = 1.0 {
didSet {
self.update()
}
}
init() {
self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.queue)
self.update()
}
func cancel() {
dispatch_source_cancel(self.source)
}
func update() {
dispatch_source_set_timer(self.source, DISPATCH_TIME_NOW, UInt64(Double(NSEC_PER_SEC) / self.rate), 0)
dispatch_source_set_event_handler(self.source, self.tick)
}
func resume() {
dispatch_resume(self.source)
}
}
var timer = Timer()
timer.tick = {
let now = NSDate()
print("\(now)")
}
timer.cancel()
timer.resume()
I have no compilation errors. But the console at the bottom of the playground shows nothing. If I add
timer.tick()
It outputs the result of the current date, apparently executing tick function once. I followed Matt's example in his book pretty closely (making small changes for education purposes). So I'm left with not knowing if
A) It's just fine and will work fine when I move it to real code, it just doesn't show anywhere apparent in the Playground output B) Somethings not missing and it's not really firing
回答1:
Once a source has been cancelled by dispatch_source_cancel
, it will never call its event handler again. You cannot reenable the source with dispatch_resume
after cancelling it; you must create a new source.
To make your playground work, you must remove the call to timer.cancel()
.
Furthermore, after the entire playground script has been executed, the playground process exits by default. If you want it to keep running, you need to set XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
.
So make the end of your script look like this:
var timer = Timer()
timer.tick = {
let now = NSDate()
print("\(now)")
}
timer.resume()
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
来源:https://stackoverflow.com/questions/33379433/cant-get-my-timer-in-swift-to-fire-in-playground