I have made a timer using DispatchSourceTimer like this:
class Timer: : NSObject, ObservableObject {
@Published var counterTime: Int = 0
var timer: DispatchSourceTimer?
func startTimer() {
let queue = DispatchQueue(label: "com.app.watchkitapp", qos: .userInteractive)
timer = DispatchSource.makeTimerSource(flags: .strict, queue: queue) <--- Xcode point out the error at this line
timer?.schedule(deadline: .now(), repeating: 1)
timer?.setEventHandler {
DispatchQueue.main.async {
self.counterTime += 1
}
}
timer?.resume()
}
func stopTimer() {
timer?.suspend()
}
func resetTimer() {
timer?.cancel()
self.counterTime = 0
}
}
But every time I try to execute the "stopTimer()" function (to stop the timer), I encounter this error:
Thread 1: EXC_BREAKPOINT (code=1, subcode=0x102f34210)
By the way, I want to make a timer that can start, pause and reset in watchos. Thank you!
I saw this error on the stack trace, the document also mentions about it.
libdispatch.dylib`:
0x10274521c <+0>: mov x8, x0
0x102745220 <+4>: stp x20, x21, [sp, #-0x10]!
0x102745224 <+8>: adrp x20, 6
0x102745228 <+12>: add x20, x20, #0x650 ; "BUG IN CLIENT OF LIBDISPATCH: Release of a suspended object"
0x10274522c <+16>: adrp x21, 40
0x102745230 <+20>: add x21, x21, #0x228 ; gCRAnnotations
0x102745234 <+24>: str x20, [x21, #0x8]
0x102745238 <+28>: str x8, [x21, #0x38]
0x10274523c <+32>: ldp x20, x21, [sp], #0x10
-> 0x102745240 <+36>: brk #0x1
It is a programmer error to release an object that is currently suspended, because suspension implies that there is still work to be done. Therefore, always balance calls to this method with a corresponding call to dispatch_resume before disposing of the object. The behavior when releasing the last reference to a dispatch object while it is in a suspended state is undefined.
I think you're not allowed to release a dispatch_source this way. You can change it like this. And I also recommend validating the timer existence whenever start
or stop
to avoid initializing multiple times.
func startTimer() {
guard timer == nil else { return }
...
}
func stopTimer() {
timer?.cancel()
timer = nil
}
You may want to take a look at this answer.