I'm following the suggestions given in this answer. Still my timer is sometimes not nil
func recreateTimer(){
let timerLog = OSLog(subsystem: "LocationLogger", category: "Timer")
guard shouldUseTimer == true else {
os_log("we are using CoreMotion, no need to set timer", log: timerLog, type: .error)
return
}
if dwellingTimer != nil{
dwellingTimer?.invalidate()
dwellingTimer = nil
}
lastDwelling = lastLocation
os_log("Moved more than 160 | invalidated previous timer began new timer", log: timerLog, type: .error)
DispatchQueue.main.async { [weak self] in
guard self?.dwellingTimer == nil else{
os_log("Timer was not niled!!!", log: timerLog, type: .error)
return
}
self?.dwellingTimer = Timer.scheduledTimer(withTimeInterval: 60, repeats: false, block: { timer in
os_log("we reached 1 minute of no movement",log: timerLog, type: .fault)
self?.locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
self?.beginMotionTracking()
os_log("Timer is deallocated & invalidated | Accuracy: %{public}f | RemainingTime: %{public}f",log: timerLog, type: .fault,(self?.locationManager.desiredAccuracy)!, UIApplication.shared.remainingTime())
})
}
os_log("New Timer is 'likely' set now", log: timerLog, type: .error)
}
Sometimes I get hits on
os_log("we are using CoreMotion, no need to set timer", log: timerLog, type: .error).
Thanks to solenoid and Paulw11 comments, I learned that all executions related to a timer should be done in a serial manner.
Also see invalidate
You must send this message from the thread on which the timer was installed. If you send this message from another thread, the input source associated with the timer may not be removed from its run loop, which could prevent the thread from exiting properly.
So in addition to invalidating and nilling (you don't want to give non-nil
for an object that no longer conveys any meaning), make sure that you: