Apple Watch显示器睡眠暂停NSTimer,但WKInterfaceTimer一直在倒计时



根据Apple文档,将同时使用WKInterfaceTimer(Watch本地,倒计时,但结束时不触发任何事件)和NSTimer(计时器结束时触发方法)。因此,我的应用程序接口控制器中同时有一个NSTimer和一个WKInterfaceTimer。在模拟器上,在WatchApp运行时的所有方案上;当手表处于唤醒或睡眠模式(按照苹果手册中的说明使用模拟器锁定/解锁)时,WKInterfaceTimer会继续倒计时(应该如此)。

然而,在真正的物理手表上,这两个计时器在手表显示睡眠(断电)和清醒状态时表现不同。睡眠模式暂停接口控制器的NSTimer,但WKInterfaceTimer继续倒计时(应该如此)。

因此,两个定时器在Apple Watch第一次物理睡眠时立即失去同步(NSTimer暂停,WKInterfaceTimer继续倒计时)。寻求其他人的体验,以及是否有人实施了一种好的方法来保持NSTimer和WKInterfaceTime同步,而不管是观看模式(睡眠还是清醒)。

似乎可以存储倒计时的结束时间(例如,在NSUserDefaults中),然后在willActivate上重新设置NSTimer,使其在正确的时间完成。或者,您可以调用iPhone应用程序来安排本地通知,但不能保证通知会发送到您的手表,因此这可能不适用于您。

我的研究结论是,根据当前版本WatchKit的苹果文档,您需要两个计时器:Apple Watch上的WK计时器和iPhone上的NSTimer。2个定时器应同步启动/启动,WK定时器在唤醒/睡眠模式下继续倒计时,NSTimer的工作是在定时器结束时发出警报/发送通知。

要使两个计时器保持同步,您需要在用户启动Apple Watch WK计时器后立即启动iPhone NSTimer。

当Apple Watch屏幕变为空白时,它会使应用程序进入睡眠状态,并暂停您启动的Timer,直到应用程序返回前台
这在模拟器中不会发生,但会在实际设备上造成问题
WKInterfaceTimer不受影响,因为它基于未来的日期并在内部处理。

因此,在应用程序返回前台后保持计时器同步,只需比较Timer块中的两个日期并观察这两个日期之间的差异即可。

在以下示例中,如果您只想更新计时器并知道倒计时何时完成,那么以下内容就足够了:

//Globally declared
@IBOutlet var interfaceTimerCountDown: WKInterfaceTimer!
var countdownToDate: Date?
func startCountdown(from count: TimeInterval) {
//Create a future date to which the countdown will count to
countdownToDate = Date().addingTimeInterval(count)

//Set and Start the WKInterfaceTimer
interfaceTimerCountDown.setDate(countdownToDate!)
interfaceTimerCountDown.start()

//Start your own Timer
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] (timer) in
//Get current date
let currentDate = Date()

//Get difference between future date and current date
let dxTimeInSeconds = self?.countdownToDate!.timeIntervalSince(currentDate) ?? 0
print(dxTimeInSeconds)

//Check if countdown has completed
if dxTimeInSeconds <= 0 {
//...do something
print("Countdown complete!")

timer.invalidate()
}
}
}

但是

WKInterfaceTimerTimer将在几毫秒内不同步,因此,如果您想在更新WKInterfaceTimer计数的同时准确地更新UI,则上述逻辑将不够
在我的情况下,我想更新一个图像;就像一个环形动画&我绕过它的唯一方法是为WKInterfaceLabel+AWKInterfaceGroup转储WKInterfaceTimer,并在计时器块内手动更新标签和组的背景图像。

自定义解决方案:

//Declared globally
//for image; to simulate a ring animation image
@IBOutlet var group_lblTimerCount: WKInterfaceGroup!
//Simple label inside a WKInterfaceGroup
@IBOutlet var lblTimerCount: WKInterfaceLabel! //inside group_lblTimerCount
var countdownToDate: Date?
func startCountdown(from count: Int) {
//Create a future date to which the countdown will count to
countdownToDate = Date().addingTimeInterval(TimeInterval(count))

//Update Label and UI
updateTimerLabel(to: count,
from: count)

//Start your own Timer
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] (timer) in
//Get current date
let currentDate = Date()

//Get difference between future date and current date
let dxTimeInSeconds = self?.countdownToDate!.timeIntervalSince(currentDate) ?? 0

//Update Label and UI
let dxTimeInSeconds_Int = Int(round(dxTimeInSeconds))
self?.updateTimerLabel(to: dxTimeInSeconds_Int,
from: count)

//Check if countdown has completed
if dxTimeInSeconds <= 0 {
//...do something
print("Countdown complete!")

//Stop timer
timer.invalidate()
}
}
}
func updateTimerLabel(to count: Int, from total: Int) {
lblTimerCount.setText("(count)")

updateTimerRing(to: count,
from: total)
}
func updateTimerRing(to count: Int, from total: Int) {
/*
I have 60 images for the ring named from "ring60" to "ring0"
Generated at: http://hmaidasani.github.io/RadialChartImageGenerator
*/
let numberOfImages = 60 //The total number of images you have
let imageIndex = "(Int(count * numberOfImages/total))"
let imageName = "ring(imageIndex)"

group_lblTimerCount.setBackgroundImageNamed(imageName)
}

附言:我试图找到一个优雅的解决方案来解决这一切,但找不到一个现成的例子,所以我正在分享我最终得到的结果。

希望它能帮助某人
:)

相关内容

  • 没有找到相关文章

最新更新