每隔X分钟在后台执行函数无法正常工作

3
我使用这段代码来每隔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个回答

5
请参考iOS应用程序编程指南:应用状态和多任务处理中的“后台执行和多任务处理”章节,以了解更多相关信息。例如,您可以将应用程序保持在后台运行几分钟以完成某些有限长度的任务;或者,如果应用程序执行以下特定列表中的某项功能,则可以在后台持续较长时间(引用自前述文档):
  • 在后台向用户播放声音内容的应用程序,例如音乐播放器应用程序
  • 在后台记录音频内容的应用程序
  • 始终让用户知道他们的位置的应用程序,例如导航应用程序
  • 支持VoIP(Voice over Internet Protocol)的应用程序
  • 需要定期下载和处理新内容的应用程序
  • 从外部附件接收定期更新的应用程序
实现这些服务的应用程序必须声明它们支持的服务,并使用系统框架来实现这些服务的相关方面。声明服务可让系统知道您使用了哪些服务,但在某些情况下,实际上是系统框架防止应用程序被暂停。但是,iOS电池/电源管理的基本设计原则是,随机应用程序不能(也不应该)在后台继续运行。如果您分享了您要做什么(即,在executeEveryOneMinute方法中具体要做什么),我们可以提供如何实现所需效果的建议(如果可能的话)。
如果您尝试在后台上传文件,则在iOS 7及更高版本中,您应该考虑使用带有后台会话配置的NSURLSession[NSURLSessionConfiguration backgroundSessionConfiguration:identifier];iOS 8中有类似的方法)。这将继续尝试上传(自动地,无需您进一步干预),即使应用程序已离开前台,甚至在应用程序终止后(例如,由于内存压力或崩溃)。AFNetworking提供了一个基于NSURLSession的类,AFURLSessionManager,支持此功能(尽管它不基于NSOperation)。这样,您就可以享受后台上传功能,同时符合苹果关于后台操作的指南,特别是比每60秒重试一次对电池影响小得多。
我建议您参考WWDC 2013视频的后半段,《基础网络新特性》,其中演示了这个过程(他们进行的是下载,但上传的原理相同)。请参照该视频了解更多信息。

这是我要做的事情。我有一些本地数据库中的数据(在手机上),必须确保将它们发送到服务器。我正在使用AFNetworking将数据传递到服务器。如果用户第一次尝试上传数据但失败了(例如没有网络或服务器宕机),我会将其保存在本地数据库中,并需要每隔几分钟尝试将其发送到服务器,直到成功为止。我不知道是否有更好的方法来实现这一点。 - 1110
iOS7提供了后台上传功能,可以为您完成此操作。AFNetworking还提供了基于NSURLSession的类AFURLSessionManager。请参见我的答案附录。 - Rob

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

0
计时器在主线程上运行。当应用程序进入后台时,其计时器变得无效。因此,在应用程序进入后台时,您不能执行相同的操作。

我该怎么做才能让它在前台和后台都能正常工作? - 1110

0

你不能使用计时器来完成这个任务,因为它会在后台被无效化。你可以尝试查看this


你能给我一些示例,我可以做什么? - 1110

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接