计时器被触发两次但未被取消

Timer is being fired twice and not nilled

我正在遵循 回答中给出的建议。我的计时器仍然是 有时 不是 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)
    }

有时我会点击

os_log("we are using CoreMotion, no need to set timer", log: timerLog, type: .error).

感谢 solenoid 和 Paulw11 的评论,我了解到所有与计时器相关的执行都应该以串行方式完成。

另见 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.

所以除了 and nilling(你不想给一个不再传达任何意义的对象赋予非nil),确保你:

  1. 使用同一个线程
  2. 您使用的线程是串行的
  3. 根据您对计时器进行更改的位置,您可能需要也可能不需要同步。