执行功能的背景每隔X分钟不工作

问题描述:

我用这个代码来执行功能每隔X分钟:执行功能的背景每隔X分钟不工作

- (void)executeEveryOneMinute 
{ 
    [self myFunction]; 

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

     [self executeEveryOneMinute]; 

    }); 
} 

当应用程序在前台它的工作原理。
但是,当应用程序去背景它不再工作。
当我将应用程序再次返回到前台时,它会执行一次函数。
然后再每分钟继续调用一次函数。

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

查看背景执行和多任务部分的iOS App Programming Guide: App States and Multitasking的可能性的讨论。例如,您可以让应用程序在后台运行几分钟,以完成一些有限长度的任务。或者您也可以继续在后台的一段较长时间运行的应用程序,如果它执行的功能(从上述文件引用)一个非常特别的列表中的一个:

  • 应用程式播放音频内容到在后台用户,如音乐播放器应用程序
  • 在后台录制音频内容的应用程序。
  • 应用程序,使用户在任何时候他们的位置的通知,如导航应用
  • 应用,支持互联网语音协议(VoIP)
  • 应用程序需要下载和处理新的内容定期
  • 应用从外部附件接收定期更新

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

但是,iOS电池/电源管理的基本设计原则是随机应用程序不能(也不应该)继续在后台运行。如果你分享你正在尝试做的事情(也就是你在做什么的方法),尽管如此,如果可能的话,我们可以提供有关如何达到预期效果的建议。


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

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

+0

在这里,我想要做的。我在本地数据库(在电话上)有一些数据,并且必须确保我将它们发送到服务器。我正在使用AFNetworking将数据传递给服务器。如果用户尝试第一次上传数据,但失败(例如没有互联网,或服务器关闭),我将它保存在本地数据库,我需要尝试每隔几分钟将它发送到服务器,直到成功。我不知道是否有更好的方法来做到这一点。 – 1110

+0

@ 1110 iOS7提供后台上传功能,可以为您提供后台上传功能。 AFNetworking还提供了一个基于NSURLSession的类,[AFURLSessionManager](http://cocoadocs.org/docsets/AFNetworking/2.0.0/Classes/AFHTTPSessionManager.html)。请参阅我的答案的附录。 – Rob

计时器在主线程上工作。当应用程序进入后台时,其定时器将失效。所以,当应用程序进入后台时你不能这么做。

+0

我能做些什么,使两个前景/背景这项工作? – 1110

+0

您应该启用音频,视频,位置等任何背景模式。 – Apurv

+0

我已经启用了音频和位置。 – 1110

你不能在定时器的帮助下做到这一点,因为它会在后台无效。您可以尝试检查this

+0

你能举一些我能做些什么的例子吗? – 1110

+0

@ 1110你可以尝试http://www.raywenderlich.com/29948/backgrounding-for-ios – Rushi

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

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; 
    });