保留 运行 NSTimer 切换背景和前景
Keep running NSTimer switching Background and Foreground
我正在尝试创建一个由用户在前台手动启动的 NSTimer,正如预期的那样完美运行:
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("updateCounter"), userInfo: nil, repeats: true)
其中 updateCounter()
只是更新 UI 中的 UILabel
。
现在我想要实现的是在用户离开应用程序时也得到它 运行 。我用谷歌搜索了一些东西并找到了这段代码(我在 Swift 中翻译):
func applicationDidEnterBackground(application: UIApplication) {
var bgTask = UIBackgroundTaskIdentifier()
bgTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler { () -> Void in
UIApplication.sharedApplication().endBackgroundTask(bgTask)
}
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
var vc = TimerViewController()
// Fire some methods
UIApplication.sharedApplication().endBackgroundTask(bgTask)
bgTask = UIBackgroundTaskInvalid
});
}
基本上我在这里可以理解的是,当应用程序到达后台时,我可以从我的 TimerViewController()
的新实例中触发一些方法,它应该处理后台阶段的 NSTimer
.
现在这是否意味着我需要使用这个 vc 或另一个方法,它从前台停止的确切时间开始另一个 NSTimer
(因为应用进入后台)?
如果是,要在用户再次打开应用程序时恢复我的第一个 NSTimer
(意味着再次进入前台 :D)我应该如何表现?停止第二个 NSTimer
并使用更新的计数器恢复第一个?
实际上,即使是解决方案的草图,我也很感激,我只是想弄清楚如何处理这种情况。
进一步的问题:如果上面写的是正确的,我如何管理 viewcontroller
的实例以获得 timer_value
(当从背景切换到前景或反之亦然时,类似 secondsLeft
) 的标记?
与其尝试在后台保持 NSTimer
(超过 10 分钟是不可能的),您要做的是记录计时器启动的时间并将其保存在 NSUserDefaults
中。您仍然可以每秒更新一次计时器,但只需根据开始时间重新计算标签(请记住,NSTimer
并不保证它会准时 运行;它可能会因多种原因而延迟,并且你会漂移)。
现在没有理由在后台运行。当您的视图控制器出现在屏幕上时 (viewDidAppear:
),只需根据 NSUserDefaults
中保存的开始时间再次更新标签。
没有办法在iOS到运行无限期地在后台。这是设计使然。但是,当您不在屏幕上时,您也没有理由浪费系统资源来尝试更新 UI。有空就更新吧。
我正在尝试创建一个由用户在前台手动启动的 NSTimer,正如预期的那样完美运行:
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("updateCounter"), userInfo: nil, repeats: true)
其中 updateCounter()
只是更新 UI 中的 UILabel
。
现在我想要实现的是在用户离开应用程序时也得到它 运行 。我用谷歌搜索了一些东西并找到了这段代码(我在 Swift 中翻译):
func applicationDidEnterBackground(application: UIApplication) {
var bgTask = UIBackgroundTaskIdentifier()
bgTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler { () -> Void in
UIApplication.sharedApplication().endBackgroundTask(bgTask)
}
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
var vc = TimerViewController()
// Fire some methods
UIApplication.sharedApplication().endBackgroundTask(bgTask)
bgTask = UIBackgroundTaskInvalid
});
}
基本上我在这里可以理解的是,当应用程序到达后台时,我可以从我的 TimerViewController()
的新实例中触发一些方法,它应该处理后台阶段的 NSTimer
.
现在这是否意味着我需要使用这个 vc 或另一个方法,它从前台停止的确切时间开始另一个 NSTimer
(因为应用进入后台)?
如果是,要在用户再次打开应用程序时恢复我的第一个 NSTimer
(意味着再次进入前台 :D)我应该如何表现?停止第二个 NSTimer
并使用更新的计数器恢复第一个?
实际上,即使是解决方案的草图,我也很感激,我只是想弄清楚如何处理这种情况。
进一步的问题:如果上面写的是正确的,我如何管理 viewcontroller
的实例以获得 timer_value
(当从背景切换到前景或反之亦然时,类似 secondsLeft
) 的标记?
与其尝试在后台保持 NSTimer
(超过 10 分钟是不可能的),您要做的是记录计时器启动的时间并将其保存在 NSUserDefaults
中。您仍然可以每秒更新一次计时器,但只需根据开始时间重新计算标签(请记住,NSTimer
并不保证它会准时 运行;它可能会因多种原因而延迟,并且你会漂移)。
现在没有理由在后台运行。当您的视图控制器出现在屏幕上时 (viewDidAppear:
),只需根据 NSUserDefaults
中保存的开始时间再次更新标签。
没有办法在iOS到运行无限期地在后台。这是设计使然。但是,当您不在屏幕上时,您也没有理由浪费系统资源来尝试更新 UI。有空就更新吧。