OS 深度睡眠后后台带有 NSTimer 的 X 代理应用程序无法运行

OS X agent app with NSTimer in the background is not working after deep sleep

我有一个 OS X 代理应用程序(菜单栏中的图标只有 运行s)。我的应用程序创建了一个具有随机间隔的 NSTimer 来播放声音。

func setNewTimer(timeInterval: NSTimeInterval) {
    self.timer = NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: self, selector: "playSound", userInfo: nil, repeats: false)
NSRunLoop.currentRunLoop().addTimer(self.timer!, forMode: NSRunLoopCommonModes)
    NSLog("Timer created for interval: \(timeInterval)")
}

该应用程序在我启动后一切正常,并继续在其他应用程序中进行其他工作。它按预期随机播放声音。

如果计算机短暂休眠然后恢复,应用程序将按预期继续随机播放声音。

但是,如果我的电脑长时间休眠(例如整夜),应用程序将不再播放声音。

问题可能是如果计算机进入深度睡眠,定时器可能会被禁用?或者(最好)有没有办法检测计算机是否从睡眠中醒来,以便我可以重置我的计时器?

注意:每次调用此函数时,我都会先 self.timer.invalidate() 并重新计算 timeInterval。在睡眠时间(例如 23:00 到 08:00 )计时器不会 运行,而是会创建一个从 23:00 到 08:00 的间隔,以便它 'fires'第二天早上。

发现一段时间没有回复,我自己想出了一个解决办法。解决方案非常简单,因为我只需要注册睡眠和唤醒通知(我将代码更新为 Swift 3):

// App should get notifified when it goes to sleep
func receiveSleepNotification(_ notification: Notification) {
    NSLog("Sleep nottification received: \(notification.name)")
    // do invalidation work
}

/// App should get notified when the PC wakes up from sleep
func receiveWakeNotification(_ notification: Notification) {
    NSLog("Wake nottification received: \(notification.name)")
    // Reset/Restart tasks
}

func registerForNotitications() {
    //These notifications are filed on NSWorkspace's notification center, not the default
    // notification center. You will not receive sleep/wake notifications if you file
    //with the default notification center.
    NSWorkspace.shared().notificationCenter.addObserver(self, selector: #selector(AppDelegate.receiveSleepNotification(_:)), name: NSNotification.Name.NSWorkspaceWillSleep, object: nil)
    NSWorkspace.shared().notificationCenter.addObserver(self, selector: #selector(AppDelegate.receiveWakeNotification(_:)), name: NSNotification.Name.NSWorkspaceDidWake, object: nil)
}

func deRegisterFromNotifications() {
    NSWorkspace.shared().notificationCenter.removeObserver(self)
}