【问题标题】:NSTimer continue during sleep modeNSTimer 在睡眠模式下继续
【发布时间】:2013-12-09 05:30:06
【问题描述】:

我有一个计时器应用程序,它使用 NSTimer 来跟踪分钟数。即使设备进入睡眠模式,如何保持计时器运行?谢谢!

【问题讨论】:

  • 您需要更新您的问题,说明为什么您认为需要计时器在设备处于睡眠状态时继续运行。很可能有更好的解决方案,但这取决于您需要什么。

标签: nstimer sleep


【解决方案1】:

您可以使用墙上时间。具体来说,我建议您查看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")
}

【讨论】:

    【解决方案2】:

    您实际上可以使用使用挂钟的 dispatch_walltime(),而不是使用 NSTimer 注册睡眠/唤醒通知。

    这里有一些文档:https://developer.apple.com/library/archive/documentation/General/Conceptual/ConcurrencyProgrammingGuide/GCDWorkQueues/GCDWorkQueues.html

    【讨论】:

      【解决方案3】:

      看看这个类,它使用“沙漏”行为为你处理睡眠/唤醒:https://github.com/jmah/MyLilTimer

      【讨论】:

        【解决方案4】:

        唤醒通知后调整

        计划的 NSTimer 实例将在睡眠期间停止。您的应用程序需要响应 NSWorkspace 的唤醒通知并调整其计时器。

        如果您不响应唤醒通知,您的计时器将恢复,但不考虑睡眠时间。

        请参阅 Apple 的技术说明 QA1340 Registering and unregistering for sleep and wake notifications 以获取相应的通知。

        示例

        考虑这种情况:

        • 创建一个在 5 分钟内触发的计时器
        • 等待 1 分钟
        • 让计算机休眠 一个小时
        • 唤醒计算机
        • 定时器在唤醒后恢复
        • 定时器在醒来 4 分钟后触发

        从计时器的角度来看,五分钟过去了。注意NSTimer 使用的语言,它使用相对持续时间而不是绝对时间,scheduledTimerWithTimeInterval:invocation:repeats:

        【讨论】:

        • 如果我没有像现在这样响应唤醒通知会怎样?
        • 您的计时器将恢复,但不考虑睡眠时间。
        • 我可以使用 NSDate 之类的东西来跟踪和添加睡眠时间吗?
        • 是的,NSDate 是获取当前日期和时间的推荐方式。您需要在醒来后重新安排计时器。
        猜你喜欢
        • 2023-03-22
        • 2012-12-02
        • 1970-01-01
        • 1970-01-01
        • 2010-12-20
        • 1970-01-01
        • 2013-03-28
        • 2013-05-28
        相关资源
        最近更新 更多