在后台每X分钟执行一次函数不起作用

时间:2022-05-02 02:29:31

I use this code to execute function every X minutes:

我用这段代码每X分钟执行一次函数:

- (void)executeEveryOneMinute
{
    [self myFunction];

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

        [self executeEveryOneMinute];

    });
}

And it works when app is in foreground.
But when app goes background it doesn't work anymore.
When I return app to foreground again it execute function once.
And continue to call function every minute again.

So how to make this to work in background too?

当应用程序在前台时,它就会起作用。但是当应用进入后台时,它就不能工作了。当我再次将app返回前台时,它会执行一次函数。继续每分钟调用一次函数。那么,如何让它在后台工作呢?

4 个解决方案

#1


4  

See the Background Execution and Multitasking section of the iOS App Programming Guide: App States and Multitasking for a discussion of the possibilities. You can, for example, keep the app running in the background for a few minutes in order to complete some finite length task. Or you can continue to run the app in the background for a longer period of time if it's performing one of a very particular list of functions (quoting from the aforementioned document):

请参阅iOS应用程序编程指南的后台执行和多任务处理部分:应用程序状态和多任务处理,以讨论各种可能性。例如,你可以让应用程序在后台运行几分钟,以完成一些有限长度的任务。或者你可以继续在后台运行这个应用程序,如果它正在执行一个非常特殊的功能列表(引用上述文档):

  • Apps that play audible content to the user while in the background, such as a music player app
  • 在后台向用户播放音频内容的应用程序,如音乐播放器应用程序
  • Apps that record audio content while in the background.
  • 在后台录制音频内容的应用程序。
  • Apps that keep users informed of their location at all times, such as a navigation app
  • 让用户随时知道自己位置的应用,比如导航应用
  • Apps that support Voice over Internet Protocol (VoIP)
  • 支持网络语音协议(VoIP)的应用
  • Apps that need to download and process new content regularly
  • 需要定期下载和处理新内容的应用程序
  • Apps that receive regular updates from external accessories
  • 从外部附件接收定期更新的应用程序

Apps that implement these services must declare the services they support and use system frameworks to implement the relevant aspects of those services. Declaring the services lets the system know which services you use, but in some cases it is the system frameworks that actually prevent your application from being suspended.

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

But, a fundamental design principle in iOS battery/power management is that random apps can not (and should not) continue to run in the background. If you share what precisely you're trying to do (namely, what precisely you're doing inside that executeEveryOneMinute method), though, we can offer counsel on how to achieve the desired effect, if possible.

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


If you're trying to have an upload continue in the background, in iOS 7 and greater, you should consider using NSURLSession with a background session configuration ([NSURLSessionConfiguration backgroundSessionConfiguration:identifier]; there is a similar method in iOS 8). This will continue to attempt to upload (automatically, without further intervention on your part) not only after your app has left the foreground, but even after the app is terminated (e.g. due to memory pressure or a crash). AFNetworking offers a NSURLSession-based class, AFURLSessionManager, which supports this (though it's not NSOperation-based). This way, you enjoy background uploads, but conforms to Apple guidelines on background operation, notably with less dramatic battery impact than retrying yourself every 60 seconds.

如果您想让上传在后台继续,在ios7或更高版本中,您应该考虑使用带有后台会话配置的NSURLSession ([NSURLSessionConfiguration backgroundSessionConfiguration:identifier];iOS 8中也有类似的方法,不仅在你的app离开前台后,甚至在app被终止后(如内存压力或崩溃),它还会继续尝试上传(自动,不需要你的进一步干预)。AFURLSessionManager是一个基于nsurlessionmanager的类,它支持这个类(虽然它不是基于nsoperbased)。通过这种方式,你可以享受后台上传,但也符合苹果公司的后台操作指南,特别是与每60秒重新尝试一次相比,它对电池的影响要小得多。

I'd suggest you refer to the latter part of WWDC 2013 video What’s New in Foundation Networking, which demonstrates this process (they're doing a download, but the idea is the same for uploads).

我建议你参考一下WWDC 2013年的视频《Foundation Networking》的后一部分,它展示了这个过程(他们正在做下载,但上传的想法是一样的)。

#2


0  

Timer works on Main thread. When application goes into background, its timers become invalid. So, you cant do the same when application goes into background.

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

#3


0  

You can't do this with help of timer as it will be invalidated in background. You can try check this.

你不能在定时器的帮助下做这件事,因为它在后台是无效的。你可以试试这个。

#4


0  

You should use background tasks to achieve what you want

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

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

#1


4  

See the Background Execution and Multitasking section of the iOS App Programming Guide: App States and Multitasking for a discussion of the possibilities. You can, for example, keep the app running in the background for a few minutes in order to complete some finite length task. Or you can continue to run the app in the background for a longer period of time if it's performing one of a very particular list of functions (quoting from the aforementioned document):

请参阅iOS应用程序编程指南的后台执行和多任务处理部分:应用程序状态和多任务处理,以讨论各种可能性。例如,你可以让应用程序在后台运行几分钟,以完成一些有限长度的任务。或者你可以继续在后台运行这个应用程序,如果它正在执行一个非常特殊的功能列表(引用上述文档):

  • Apps that play audible content to the user while in the background, such as a music player app
  • 在后台向用户播放音频内容的应用程序,如音乐播放器应用程序
  • Apps that record audio content while in the background.
  • 在后台录制音频内容的应用程序。
  • Apps that keep users informed of their location at all times, such as a navigation app
  • 让用户随时知道自己位置的应用,比如导航应用
  • Apps that support Voice over Internet Protocol (VoIP)
  • 支持网络语音协议(VoIP)的应用
  • Apps that need to download and process new content regularly
  • 需要定期下载和处理新内容的应用程序
  • Apps that receive regular updates from external accessories
  • 从外部附件接收定期更新的应用程序

Apps that implement these services must declare the services they support and use system frameworks to implement the relevant aspects of those services. Declaring the services lets the system know which services you use, but in some cases it is the system frameworks that actually prevent your application from being suspended.

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

But, a fundamental design principle in iOS battery/power management is that random apps can not (and should not) continue to run in the background. If you share what precisely you're trying to do (namely, what precisely you're doing inside that executeEveryOneMinute method), though, we can offer counsel on how to achieve the desired effect, if possible.

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


If you're trying to have an upload continue in the background, in iOS 7 and greater, you should consider using NSURLSession with a background session configuration ([NSURLSessionConfiguration backgroundSessionConfiguration:identifier]; there is a similar method in iOS 8). This will continue to attempt to upload (automatically, without further intervention on your part) not only after your app has left the foreground, but even after the app is terminated (e.g. due to memory pressure or a crash). AFNetworking offers a NSURLSession-based class, AFURLSessionManager, which supports this (though it's not NSOperation-based). This way, you enjoy background uploads, but conforms to Apple guidelines on background operation, notably with less dramatic battery impact than retrying yourself every 60 seconds.

如果您想让上传在后台继续,在ios7或更高版本中,您应该考虑使用带有后台会话配置的NSURLSession ([NSURLSessionConfiguration backgroundSessionConfiguration:identifier];iOS 8中也有类似的方法,不仅在你的app离开前台后,甚至在app被终止后(如内存压力或崩溃),它还会继续尝试上传(自动,不需要你的进一步干预)。AFURLSessionManager是一个基于nsurlessionmanager的类,它支持这个类(虽然它不是基于nsoperbased)。通过这种方式,你可以享受后台上传,但也符合苹果公司的后台操作指南,特别是与每60秒重新尝试一次相比,它对电池的影响要小得多。

I'd suggest you refer to the latter part of WWDC 2013 video What’s New in Foundation Networking, which demonstrates this process (they're doing a download, but the idea is the same for uploads).

我建议你参考一下WWDC 2013年的视频《Foundation Networking》的后一部分,它展示了这个过程(他们正在做下载,但上传的想法是一样的)。

#2


0  

Timer works on Main thread. When application goes into background, its timers become invalid. So, you cant do the same when application goes into background.

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

#3


0  

You can't do this with help of timer as it will be invalidated in background. You can try check this.

你不能在定时器的帮助下做这件事,因为它在后台是无效的。你可以试试这个。

#4


0  

You should use background tasks to achieve what you want

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

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