当iOS应用程序进入后台时,长时间运行的任务是否会被暂停?

75

是的,我知道如果我希望我的应用程序对用户的多任务操作(例如切换到另一个应用程序)做出响应,我应该处理

- (void)applicationWillResignActive:(UIApplication *)application
- (void)applicationDidBecomeActive:(UIApplication *)application
如果我的应用正在执行一个相当耗时的操作(比如下载一个大文件),而用户导致我的应用进入后台,那么这个操作会自动暂停并在用户返回我的应用时恢复吗?
当我的应用进入后台或在前台恢复时,背后究竟会发生什么?
如果在用户将我的应用放到后台时,我的应用的执行正处于一个方法的中间怎么办?
例如,我的应用正在执行……
for (int i = 1 to 10000K) {
    do some calculation;
}

当 i== 500K 时,用户切换到另一个应用程序。我的应用程序中的 for 循环会发生什么?


4
我认为这是个很好的问题,但你有没有花时间测试和弄清楚当应用转到后台时会发生什么?我的意思是,在循环中的某个地方放置一个NSLog并查看会发生什么...... - MiguelB
2
首先,建议遵循micpringle的建议。其次,如果我没记错的话,有七个非常特定的API允许在后台运行。看看它们是否符合要求。如果不符合,也许你需要重新设计应用程序的方式。 - J. Steen
3个回答

78
文档中得知,applicationDidEnterBackground(_:)方法需要尽快返回。该方法有大约5秒的时间来执行任何任务并返回结果。如果该方法在超时之前没有返回,则您的应用程序将被终止并清除内存。如果您需要更多时间来执行任何最后的任务,请调用beginBackgroundTask(expirationHandler:)从系统请求额外的执行时间。请尽早调用beginBackgroundTask(expirationHandler:),因为系统需要时间来处理您的请求,所以在获得任务断言之前,系统有可能会挂起您的应用程序。例如,在applicationDidEnterBackground(_:)方法的最后一步调用beginBackgroundTask(expirationHandler:),并期望您的应用程序能够继续运行是错误的做法。如果您在主线程上描述的长时间运行操作在应用程序进入后台后需要超过5秒才能完成,则您的应用程序将被终止。主线程将被阻塞,并且您无法及时从-applicationDidEnterBackground:方法中返回。如果您的任务正在后台线程上运行(如果执行时间很长,则确实应该这样做),则如果应用程序从-applicationDidEnterBackground:返回,则该线程似乎已被暂停(根据此答案中的讨论)。当应用程序重新进入前台时,该线程将被恢复。无论如何,您仍应准备好在应用程序处于后台时清理它的工作以防止其被终止。

这很令人困惑。beginBackgroundTaskWithExpirationHandler授予您的应用程序10分钟(非常长时间!)来完成任务,但是“在后台运行时随时准备好应用程序被终止”???哪个是真的?我的约10秒钟的任务使用CoreGraphics来渲染图像(作为缩略图)并在后台处理它们,但当应用程序进入后台时,它们会永远挂起!!!应用程序在'beginBackgroundTaskWithExpirationHandler'期间允许做什么? - Motti Shneor

12

如果您正在执行可能需要一些时间的操作,并且不想中断它,则可以通过在UIBackground Task中执行来延长操作的时间。

{
    UIBackgroundTaskIdentifier  taskId = 0;
    taskId = [application beginBackgroundTaskWithExpirationHandler:^{
        taskId = UIBackgroundTaskInvalid;
    }];

// Execute long process. This process will have 10 mins even if your app goes in background mode.

}

当后台任务过期(10分钟)时,“handler”所指的块参数将会发生什么。

这是链接到文档的链接。


当应用程序进入后台时,这可以正常工作。当应用程序被终止时,例如 applicationWillTerminate(_ application: UIApplication),应该采取什么解决方案? - Neeraj Joshi
你能详细说明一下吗?1)'beginBackgroundTaskWithExpirationHandler'的正确调用时间是什么时候?我可以在'applicationWillResignActive' 或 'applicationDidEnterBackground'中这样做吗?2)在应用程序处于后台时,到期处理程序会被调用吗?在哪个线程/队列上?在此处理程序中可以进行什么操作,而不可以进行什么操作?3)我的应用程序在后台使用CoreGraphics来渲染图像-有些CG方法会挂起它们的线程。它们在这样的“backgroundTask”中更能生存吗? - Motti Shneor

0
如上所述,有一些情况下您的应用程序在后台运行,苹果可以根据您的操作允许或拒绝。

https://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html

更重要的是,如果您符合这些类别之一,您的应用程序刷新率将由苹果算法确定,该算法考虑了您在该设备上使用应用程序与其他应用程序的情况。如果您的应用程序使用频率更高,则会分配更多的后台时间。这只是一个变量,但您可以想象后台时间分配因应用程序而异,而不在您的控制范围内。

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