在后台每隔X分钟执行一次功能并不起作用

时间:2014-06-12 08:39:43

标签: ios iphone objective-c ios7 nsthread

我使用此代码每隔X分钟执行一次函数:

- (void)executeEveryOneMinute
{
    [self myFunction];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(60 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        [self executeEveryOneMinute];

    });
}

当应用处于前台时,它可以正常工作 但是,当应用程序进入后台时,它将不再起作用 当我再次将应用程序返回到前台时,它会执行一次函数 并继续每分钟呼叫功能。

那么如何让它在后台工作呢?

4 个答案:

答案 0 :(得分:4)

有关可能性的讨论,请参阅iOS App Programming Guide: App States and Multitasking后台执行和多任务部分。例如,您可以让应用程序在后台运行几分钟,以完成一些有限长度的任务。或者,如果它正在执行一个非常特殊的功能列表(引自上述文档),您可以继续在后台运行该应用程序更长的时间段:

  
      
  • 在后台播放用户可听内容的应用,例如音乐播放器应用
  •   
  • 在后台录制音频内容的应用。
  •   
  • 随时向用户通知其位置信息的应用,例如导航应用
  •   
  • 支持互联网协议语音(VoIP)的应用
  •   
  • 需要定期下载和处理新内容的应用
  •   
  • 从外部附件接收定期更新的应用
  •   
     

实施这些服务的应用必须声明其支持的服务,并使用系统框架来实现这些服务的相关方面。声明服务可以让系统知道您使用哪些服务,但在某些情况下,系统框架实际上会阻止您的应用程序被暂停。

但是,iOS电池/电源管理的基本设计原则是随机应用程序不能(也不应该)继续在后台运行。如果您正在分享您正在尝试做的事情(即,您在executeEveryOneMinute方法中正在做什么),我们可以就如何实现所需效果提供建议。


如果您尝试在后台继续上传,在iOS 7及更高版本中,您应该考虑将NSURLSession与后台会话配置[NSURLSessionConfiguration backgroundSessionConfiguration:identifier]一起使用;有类似的方法iOS 8)。这将继续尝试上传(自动,无需您的进一步干预),不仅在您的应用程序离开前台后,甚至在应用程序终止后(例如由于内存压力或崩溃)。 AFNetworking提供基于NSURLSession的类AFURLSessionManager,它支持此类(虽然它不是基于NSOperation)。通过这种方式,您可以享受后台上传,但符合Apple关于后台操作的指导原则,特别是电池影响不如每60秒重试一次。

我建议你参考WWDC 2013视频What’s New in Foundation Networking的后半部分,它展示了这个过程(他们正在进行下载,但上传的想法是一样的。)

答案 1 :(得分:0)

计时器适用于主线程。当应用程序进入后台时,其定时器将变为无效。因此,当应用程序进入后台时,你不能这样做。

答案 2 :(得分:0)

您无法在计时器的帮助下执行此操作,因为它将在后台无效。您可以尝试检查this

答案 3 :(得分:0)

您应该使用后台任务来实现您想要的目标

UIApplication*    app = [UIApplication sharedApplication];
task = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:task];
        task = UIBackgroundTaskInvalid;
    }];
// Start the long-running task and return immediately.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Do the work associated with the task.
        NSLog(@"Started background task timeremaining = %f", [app backgroundTimeRemaining]);
        if (connectedToNetwork) {
            // do work son...
        }

        [app endBackgroundTask:task];
        task = UIBackgroundTaskInvalid;
    });