计时器不会在 WatchKit 上每秒触发一次
Timer not firing every second on WatchKit
这个计时器不是每秒触发一次,当我检查日志时 UI 它似乎每 3-4 秒触发一次。
func startTimer() {
print("start timer")
timer = Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(timerDidFire),
userInfo: nil,
repeats: true)
}
func timerDidFire(timer: Timer) {
print("timer")
updateLabels()
}
这只是由于功能不足而在 Watch 上发生的事情,还是我的代码有问题?
如果需要,这里是日志:
0.0396000146865845
3.99404102563858
7.97501903772354
11.9065310359001
编辑:
需要说明的是,我每秒更新的是锻炼计时器,所以它需要每秒更新一次。
如果您的应用正忙于做其他事情,这会阻止或延迟 运行 循环检查触发时间是否已重复过去,the timer will only fire once during that period:
A repeating timer always schedules itself based on the scheduled firing time, as opposed to the actual firing time. For example, if a timer is scheduled to fire at a particular time and every 5 seconds after that, the scheduled firing time will always fall on the original 5 second time intervals, even if the actual firing time gets delayed. If the firing time is delayed so far that it passes one or more of the scheduled firing times, the timer is fired only once for that time period; the timer is then rescheduled, after firing, for the next scheduled firing time in the future.
顺便说一句,根据对更改的响应(例如,观察)或对事件的反应(例如,完成处理程序)来更新您的 UI 可能更有效。
如果在计时器间隔内没有任何变化,这可以避免在驱动检查但实际上没有要执行的 UI 更新时为应用程序创建繁忙的工作。
它还可以防止忽略触发间隔内的多次更改,因为计时器驱动的模式只会显示 UI 中的最后一次更改。
考虑使用 WKInterfaceTimer 标签代替您用来显示时间的标签:
A WKInterfaceTimer object is a special type of label that displays a
countdown or count-up timer. Use a timer object to configure the
amount of time and the appearance of the timer text. When you start
the timer, WatchKit updates the displayed text automatically on the
user’s Apple Watch without further interactions from your extension.
Apple Docs.
WatchOS 将负责及时更新。 OS 为您处理标签,但您必须跟踪经过的时间:您只需设置一个 NSDate 即可(请参见下面的示例)。
示例代码。
在您的 WKInterfaceController 子类中:
// Hook up a reference to the timer.
@IBOutlet var workoutTimer: WKInterfaceTimer!
// Keep track of the time the workout started.
var workoutStartTime: NSDate?
func startWorkout() {
// To count up use 0.0 or less, otherwise the timer counts down.
workoutTimer.setDate(NSDate(timeIntervalSinceNow: 0.0))
workoutTimer.start()
self.workoutStartTime = NSDate()
}
func stopWorkout() {
workoutTimer.stop()
}
func workoutSecondsElapsed() -> NSTimeInterval? {
// If the timer hasn't been started then return nil
guard let startTime = self.workoutStartTime else {
return nil
}
// Time intervals from past dates are negative, so
// multiply by -1 to get the elapsed time.
return -1.0 * self.startTime.timeIntervalSinceNow
}
综合博客条目:here。
截至 2021 年,(Foundation) Timer 对象支持容差变量(以秒为单位)。设置 timer.tolerance = 0.2,你应该每秒(+/- 0.2 秒)起火。如果您只是更新 GUI,确切的时间间隔并不是那么重要,但这应该比不使用容差值更可靠。您需要单独创建计时器,并手动添加到 运行 队列,如下所示... (Swift)
import Foundation
// Set up timer to fire every second
let newTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) {timer in
self.timerFired()
}
newTimer.tolerance = 0.2 // For visual updates, 0.2 is close enough
RunLoop.current.add(newTimer, forMode: .common)
这个计时器不是每秒触发一次,当我检查日志时 UI 它似乎每 3-4 秒触发一次。
func startTimer() {
print("start timer")
timer = Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(timerDidFire),
userInfo: nil,
repeats: true)
}
func timerDidFire(timer: Timer) {
print("timer")
updateLabels()
}
这只是由于功能不足而在 Watch 上发生的事情,还是我的代码有问题?
如果需要,这里是日志:
0.0396000146865845
3.99404102563858
7.97501903772354
11.9065310359001
编辑:
需要说明的是,我每秒更新的是锻炼计时器,所以它需要每秒更新一次。
如果您的应用正忙于做其他事情,这会阻止或延迟 运行 循环检查触发时间是否已重复过去,the timer will only fire once during that period:
A repeating timer always schedules itself based on the scheduled firing time, as opposed to the actual firing time. For example, if a timer is scheduled to fire at a particular time and every 5 seconds after that, the scheduled firing time will always fall on the original 5 second time intervals, even if the actual firing time gets delayed. If the firing time is delayed so far that it passes one or more of the scheduled firing times, the timer is fired only once for that time period; the timer is then rescheduled, after firing, for the next scheduled firing time in the future.
顺便说一句,根据对更改的响应(例如,观察)或对事件的反应(例如,完成处理程序)来更新您的 UI 可能更有效。
如果在计时器间隔内没有任何变化,这可以避免在驱动检查但实际上没有要执行的 UI 更新时为应用程序创建繁忙的工作。
它还可以防止忽略触发间隔内的多次更改,因为计时器驱动的模式只会显示 UI 中的最后一次更改。
考虑使用 WKInterfaceTimer 标签代替您用来显示时间的标签:
A WKInterfaceTimer object is a special type of label that displays a countdown or count-up timer. Use a timer object to configure the amount of time and the appearance of the timer text. When you start the timer, WatchKit updates the displayed text automatically on the user’s Apple Watch without further interactions from your extension. Apple Docs.
WatchOS 将负责及时更新。 OS 为您处理标签,但您必须跟踪经过的时间:您只需设置一个 NSDate 即可(请参见下面的示例)。
示例代码。
在您的 WKInterfaceController 子类中:
// Hook up a reference to the timer. @IBOutlet var workoutTimer: WKInterfaceTimer! // Keep track of the time the workout started. var workoutStartTime: NSDate? func startWorkout() { // To count up use 0.0 or less, otherwise the timer counts down. workoutTimer.setDate(NSDate(timeIntervalSinceNow: 0.0)) workoutTimer.start() self.workoutStartTime = NSDate() } func stopWorkout() { workoutTimer.stop() } func workoutSecondsElapsed() -> NSTimeInterval? { // If the timer hasn't been started then return nil guard let startTime = self.workoutStartTime else { return nil } // Time intervals from past dates are negative, so // multiply by -1 to get the elapsed time. return -1.0 * self.startTime.timeIntervalSinceNow }
综合博客条目:here。
截至 2021 年,(Foundation) Timer 对象支持容差变量(以秒为单位)。设置 timer.tolerance = 0.2,你应该每秒(+/- 0.2 秒)起火。如果您只是更新 GUI,确切的时间间隔并不是那么重要,但这应该比不使用容差值更可靠。您需要单独创建计时器,并手动添加到 运行 队列,如下所示... (Swift)
import Foundation
// Set up timer to fire every second
let newTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) {timer in
self.timerFired()
}
newTimer.tolerance = 0.2 // For visual updates, 0.2 is close enough
RunLoop.current.add(newTimer, forMode: .common)