【问题标题】:How to run timer though the app entered background or is terminated如何在应用程序进入后台或终止时运行计时器
【发布时间】:2014-12-11 20:38:31
【问题描述】:
在我的应用程序中,我有一个 NSTimer 和一个选择器 - (void)TimerCount。我还有一个整数int CountNum,每0.01秒加1(CountNum = CountNum + 1)。
Timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(TimerCount) userInfo:nil repeats:YES];
我希望计时器在应用程序终止或进入后台时恢复。我该怎么做?
【问题讨论】:
标签:
ios
objective-c
nstimer
appdelegate
【解决方案1】:
您可以使用 NSuserdefaults 来保存您的 countNum,只要用户退出应用程序,它就会被保存。只需将其调用到 APPDELEGATE 函数- (void)applicationWillTerminate:(UIApplication *)application {
NSUserDefault *defaults = [NSUser Defaults standardUserDefaults];
[defaults setInteger: countNum forKeys:@"ANY_KEY_HERE"];
[defaults synchronise];
上面的代码会保存你的countNum,但是当用户终止或进入后台时你必须保存它。
当用户进入前台时,您可以调用以检索您的 countNum
NSUserDefault *defaults = [NSUser Defaults standardUserDefaults];
yourCountNum = [default getIntegerForKeys: @"ANY_KEY_HERE"];
【解决方案2】:
一些想法:
通常您不会尝试让计时器继续运行。如果您不需要,您应该避免让应用程序在后台执行任何操作。您不必要地耗尽了用户的系统资源(电池、内存、CPU 周期等)。
如果您需要在应用程序可能未运行的未来某个时间点引起用户的注意(例如,如果这是您正在实施的倒计时或类似警报的功能),请使用location notification 而不是使用计时器。
-
另外,如果您想跟踪已经过去了多少时间,使用 NSTimer 不是正确的解决方案(尤其是如果您每秒触发 100 次)。捕获开始时间,然后当您想要确定已经过去了多少时间时,您可以在未来的任何时间点获取当前时间并将其与开始时间进行比较。
这种方法的美妙之处在于您不再关心执行此过程的频率。如果您正在更新 UI,您可以每秒调用 60 次。如果应用程序在后台,则无需执行任何操作,直到将应用程序带回前台(只需将启动时间保存在持久存储中,例如NSUserDefaults,然后在应用程序启动时再次检索即可再次)。
底线是,通过从“计数器”方法转向“比较当前时间与开始时间”方法,您可以将 UI 与计时器分离。不用说,一旦你这样做了,当应用离开前台时,你就根本不需要计时器了。
如果您绝对需要在应用程序离开前台时运行计时器,有办法做到这一点(例如,请求几分钟来完成一些有限长度的任务),但只有在绝对需要时才这样做。如果您只是更新一个计数器,那么您肯定不想这样做。
【解决方案3】:
如果您的申请终止,您将无法继续处理。要在后台操作,有后台任务之类的东西,但听起来你的用例并不保证它们。因为您的递增是线性且可计算的,所以您可以将开始日期分配给 NSUserDefaults,然后在您的应用程序恢复时将其加载回来并更新您的计数。
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]] forKey:@"start_time"];
NSNumber *start = [[NSUserDefaults standardUserDefaults] objectForKey:@"start_time"];
countNum = ceil([[NSDate date] timeIntervalSince1970] * 100) - ceil([start doubleValue] * 100);