beginBackgroundTaskWithExpirationHandler调用endBackgroundTask但不是结束进程

Kap*_*isa 7 backgrounding long-running-processes ios uibackgroundtask

即使应用程序在后台进行,我也有一些长时间运行的进程.我正在调用应用程序的beginBackgroundTaskWithExpirationHandler:方法,在expirationBlock中我正在调用应用程序endBackgroundTask.这是实施:

__block UIBackgroundTaskIdentifier task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
    [[UIApplication sharedApplication] endBackgroundTask:task];
    task = UIBackgroundTaskInvalid;
}];
dispatch_queue_t queue = dispatch_queue_create("com.test.test1234", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
    // My Task goes here
});
Run Code Online (Sandbox Code Playgroud)

在某些情况下,我的串行队列有更多要执行的任务,这些任务无法在系统提供的时间内完成.因此,到期块将执行,并且我将结束UIBackgroundTaskIdentifier但不停止调度过程(我甚至无法取消调度).

Apple的文件说:

每次调用beginBackgroundTaskWithName:expirationHandler:或beginBackgroundTaskWithExpirationHandler:方法都会生成一个唯一的令牌以与相应的任务相关联.当您的应用程序完成任务时,它必须使用相应的令牌调用endBackgroundTask:方法,以让系统知道任务已完成.未能为后台任务调用endBackgroundTask:方法将导致应用程序终止.如果在启动任务时提供了过期处理程序,系统将调用该处理程序并为您提供最后一次结束任务并避免终止的机会.

所以,根据这个,如果我不打电话,endBackgroundTask:我的应用程序将被终止,这是好的.

我的问题是:对于我当前的实现,如果我调用endBackgroundTask:expirationHandler块并且我的调度队列的任务没有完成,该怎么办?我的应用程序将被终止或将被暂停?

谢谢

Jat*_* JP 12

以下是一些情况,您需要处理,beginBackgroundTaskWithExpirationHandler否则您的应用程序将使用terminate.

场景1:您的应用正在运行Foreground.你开始beginBackgroundTaskWithExpirationHandler 然后进入Background模式.你的应用程序保持活力很久.

场景2:您的应用正在运行Foreground.你开始beginBackgroundTaskWithExpirationHandler 然后进入Background模式.然后回到Foreground模式,endBackgroundTask然后你没有调用你的应用程序,execute background queue所以它将扩展下一个过程3 minute(在IOS 7介绍之后.在IOS 7之前,过程执行时间是10分钟).所以你必须取消后台队列和任务从后台队列中出来并进入前台队列.

所以这里有代码给你看.处理后台进程的最佳方法是什么.

步骤1:将 __block UIBackgroundTaskIdentifier bgTask声明为全局变量.

第2步:在applicationDidEnterBackground中添加以下代码.

- (void)applicationDidEnterBackground:(UIApplication *)application {

         bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
         bgTask = UIBackgroundTaskInvalid;
          }];

}
Run Code Online (Sandbox Code Playgroud)

第3步:应用程序进入前台模式后停止后台任务处理程序.

- (void)applicationWillEnterForeground:(UIApplication *)application {
  // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.

  [[UIApplication sharedApplication] endBackgroundTask:bgTask];

}
Run Code Online (Sandbox Code Playgroud)