【发布时间】:2013-12-09 05:30:06
【问题描述】:
我有一个计时器应用程序,它使用 NSTimer 来跟踪分钟数。即使设备进入睡眠模式,如何保持计时器运行?谢谢!
【问题讨论】:
-
您需要更新您的问题,说明为什么您认为需要计时器在设备处于睡眠状态时继续运行。很可能有更好的解决方案,但这取决于您需要什么。
我有一个计时器应用程序,它使用 NSTimer 来跟踪分钟数。即使设备进入睡眠模式,如何保持计时器运行?谢谢!
【问题讨论】:
您可以使用墙上时间。具体来说,我建议您查看DispatchSourceTimer.schedule(wallDeadline:) 或DispatchQueue.asyncAfter(wallDeadline:)
此脚本有助于了解它们的行为方式。从 Swift Playground 运行它,将你的 mac 设置为休眠 30 秒并检查结果。另外,不要让你的 mac 进入睡眠状态,做同样的实验。
import Foundation
// Pauses on sleep
let monotonicDispatchSourceTimer = DispatchSource.makeTimerSource(queue: DispatchQueue.main)
monotonicDispatchSourceTimer.schedule(deadline: DispatchTime.now() + 30)
monotonicDispatchSourceTimer.setEventHandler(handler: {
print("Hello from monotonic makeTimerSource")
})
monotonicDispatchSourceTimer.resume()
// Pauses on sleep
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 30) {
print("Hello from monotonic DispatchQueue.asyncAfter")
}
// Pauses on sleep
class TimerWrapper: NSObject {
var timer: Timer?
func run() {
timer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(fireTimer), userInfo: nil, repeats: false)
}
@objc private func fireTimer(){
print("Hello from Timer.scheduledTimer")
}
}
let timerWrapper = TimerWrapper()
timerWrapper.run()
// Doesn't pause on sleep
let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.main)
timer.schedule(wallDeadline: DispatchWallTime.now() + 30)
timer.setEventHandler(handler: {
print("Hello from DispatchSourceTimer with wall deadline")
})
timer.resume()
// Doesn't pause on sleep
DispatchQueue.main.asyncAfter(wallDeadline: DispatchWallTime.now() + 30) {
print("Hello from DispatchQueue.asyncAfter with wall deadline")
}
【讨论】:
您实际上可以使用使用挂钟的 dispatch_walltime(),而不是使用 NSTimer 注册睡眠/唤醒通知。
【讨论】:
看看这个类,它使用“沙漏”行为为你处理睡眠/唤醒:https://github.com/jmah/MyLilTimer
【讨论】:
计划的 NSTimer 实例将在睡眠期间停止。您的应用程序需要响应 NSWorkspace 的唤醒通知并调整其计时器。
如果您不响应唤醒通知,您的计时器将恢复,但不考虑睡眠时间。
请参阅 Apple 的技术说明 QA1340 Registering and unregistering for sleep and wake notifications 以获取相应的通知。
考虑这种情况:
从计时器的角度来看,五分钟过去了。注意NSTimer 使用的语言,它使用相对持续时间而不是绝对时间,scheduledTimerWithTimeInterval:invocation:repeats:。
【讨论】: