计划NSTimer当应用程序在后台?

当应用程序在后台时,人们如何处理预定的NSTimer?

比方说,我每隔一小时在应用程序中更新一些东西。

updateTimer = [NSTimer scheduledTimerWithTimeInterval:60.0*60.0 target:self selector:@selector(updateStuff) userInfo:nil repeats:YES]; 

在后台,这个计时器显然不会触发(?)。 当用户回到应用程序时会发生什么? 计时器是否仍在运行,时间相同?

如果用户在一个小时内回来,会发生什么。 它会触发所有错过的时间,还是等到下一次更新时间?

我想要做的是在应用程序进入前台后立即更新,如果应该发布的date是过去的。 那可能吗?

你不应该通过设置一个计时器来解决这个问题,因为你不允许在后台执行任何代码。 想象一下,如果用户在此期间重新启动他的iPhone或者其他边缘情况,会发生什么。

使用AppDelegate的applicationDidEnterBackground:applicationWillEnterForeground:方法来获取所需的行为。 这是更强大的方式,因为它也将工作,当你的应用程序完全被杀害,因为重新启动或内存压力。

您可以节省下次计时器在您的应用程序进入背景时将触发的时间,并检查应用程序回到前台时是否应采取行动。 在这个方法中也停止并启动计时器。 当您的应用程序正在运行时,您可以使用计时器在适当的时刻触发更新。

您可以在后台执行模式下启动计时器。 有几个技巧:

  • 您需要使用beginBackgroundTaskWithExpirationHandlerselect后台执行。
  • 要么在主线程上创buildNSTimer,要么使用[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]手动将它添加到[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]

如果你在主线程:

 { // Declare the start of a background task // If you do not do this then the mainRunLoop will stop // firing when the application enters the background self.backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier]; }]; // Make sure you end the background task when you no longer need background execution: // [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier]; [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(timerDidFire:) userInfo:nil repeats:YES]; } - (void) timerDidFire:(NSTimer *)timer { // This method might be called when the application is in the background. // Ensure you do not do anything that will trigger the GPU (eg animations) // See: http://developer.apple.com/library/ios/DOCUMENTATION/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4-SW47 } 

笔记

  • 应用程序只能获得后台执行大约10分钟(大约3分钟的iOS 7) – 在此之后,定时器将停止触发。
  • 从设备locking时的iOS 7开始,它将几乎立即暂停前台应用程序。 iOS 7应用程序被locking后,定时器不会触发。

如果您或其他人正在寻找如何在Swift的后台运行NSTimer,请将以下内容添加到您的App Delegate中:

 var backgroundUpdateTask: UIBackgroundTaskIdentifier = 0 func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { return true } func applicationWillResignActive(application: UIApplication) { self.backgroundUpdateTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({ self.endBackgroundUpdateTask() }) } func endBackgroundUpdateTask() { UIApplication.sharedApplication().endBackgroundTask(self.backgroundUpdateTask) self.backgroundUpdateTask = UIBackgroundTaskInvalid } func applicationWillEnterForeground(application: UIApplication) { self.endBackgroundUpdateTask() } 

干杯!

在后台时,这个计时器显然不会启动

这篇文章表明事情并不那么清楚。 应用程序进入后台时,应该使计时器无效,并在回到前台时重新启动计时器。 在后台运行的东西可能是可能的,但是可能会让你死亡…

你可以在这里find有关iOS多任务方法的好文档。

在iOS 8上,当应用程序处于后台(即使iPhone被locking)时,您可以以简单的方式将您的NSTimer工作到〜3分钟:

只是实现scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:方法照常你需要的地方。 在AppDelegate里面创build一个属性:

 UIBackgroundTaskIdentifier backgroundUpdateTask 

那么在你的appDelegate方法中:

 - (void)applicationWillResignActive:(UIApplication *)application { self.backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [self endBackgroundUpdateTask]; }]; } - (void) endBackgroundUpdateTask { [[UIApplication sharedApplication] endBackgroundTask: self.backgroundUpdateTask]; self.backgroundUpdateTask = UIBackgroundTaskInvalid; } - (void)applicationWillEnterForeground:(UIApplication *)application { [self endBackgroundUpdateTask]; } 

3分钟后定时器不会再开火,当应用程序将在前台回复时,它将开始再次开火

您需要在当前运行循环中添加您的计时器。

 [[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSRunLoopCommonModes]; 
 [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil]; loop = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(Update) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:loop forMode:NSRunLoopCommonModes]; 

您需要在运行循环中添加计时器( 参考 – 用于运行循环理解的Apple开发人员页面)。

 NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTimer) userInfo:nil repeats:true]; [[NSRunLoop mainRunLoop] addTimer: timer forMode:NSRunLoopCommonModes]; //funcation -(void) updateTimer{ NSLog(@"Timer update"); } 

您需要在infoPlist中添加后台工作权限(必需的后台模式)。