This is a next chapter of a question I asked a while back. I have this simplified Timer, it is inspired by the Timer object in Matt Neuburg's book.
import Foundation
import XCPlayground
class Timer {
private var queue = dispatch_queue_create("timer", nil)
private var source: dispatch_source_t!
var tick:()->() = {}
var interval:NSTimeInterval = 1
func start() {
self.stop()
self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.queue)
dispatch_source_set_timer(source, DISPATCH_TIME_NOW, UInt64(self.interval) * 1000000000, 0)
dispatch_source_set_event_handler(source, self.tick)
dispatch_resume(self.source)
}
func stop() {
if self.source != nil {
dispatch_suspend(self.source)
}
}
}
var timer = Timer()
timer.interval = 5
timer.tick = { print("now \(NSDate())") }
timer.start()
timer.stop()
timer = Timer() // <<--BAD STUFF HAPPENS HERE
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
The problem is the point where I assign a new timer to the same variable. The basic use case is that I'm done with a timer, so I stop it, but then perhaps want to create a new one and launch it.
In a playground, that marked line gives the error:
Execution was interrupted, reason: EXC_BAD_INSTRUCTION {code=EXC_I386_INVOP, subcode=0x0).
If I do something similar in my iOS app, I get an exception trace that looks like:
0: _dispatch_xref_dispose
5: MyViewController.scanTimer.setter
....
It doesn't seem to matter if it's a struct or a class. Same thing happens. I wondered if I needed a deinit
, but I haven't found an implementation of that that makes it go away.