如果用户关闭已在后台的应用程序会发生什么?

时间:2013-04-18 17:09:55

标签: ios objective-c cocoa-touch uikit appdelegate

在后台任务执行期间,如果用户杀死应用程序(已经处于后台模式)会发生什么?

想象一下:

应用程序启动任务X(具有10分钟的后台支持和必须调用的到期处理程序)。 然后,应用程序转到后台,用户就会杀死该应用程序。

我对应用程序被杀后的任务X会发生什么感到困惑。是否仍有执行的后台时间?是否会调用过期处理程序?

3 个答案:

答案 0 :(得分:3)

如果应用“已在后台”,则用户“关闭应用”!那你的问题意味着什么呢?你已经进入后台,如果你这样做了beginBackgroundTaskWithExpirationHandler:,事情就会正常进行。

你的意思是用户通过召唤“最近的应用程序”界面并进入jiggy模式并从“最近的应用程序”界面中删除应用程序来强制在后台杀死应用程序吗?然后应用程序被立即杀死;你没有收到任何通知,你正在做的任何事都被打断了。

此外,到期处理程序块唯一应该做的就是调用endBackgroundTask:。如果你被即时杀害,你无法拨打这个电话的事实并不重要!

答案 1 :(得分:1)

好的,这就是结果

在这种情况下,操作系统会向您的应用程序的进程发送SIGKILL信号,并且不会调用applicationWillTerminate方法。

以下是我对Apple文档,猜测作品和Google搜索结果的解释。

在这种情况下,您的应用程序委托的方法将被调用

- (void)applicationWillTerminate:(UIApplication *)application

来自Apple Docs的引用

  

对于不支持后台执行或不支持后台执行的应用程序   与iOS 3.x或更早版本相关联,此方法始终在调用时调用   用户退出应用程序。对于支持的应用程序   后台执行时,此方法一般不会被调用   用户退出应用程序,因为应用程序只是移动到   那种情况下的背景。 但是,可以调用此方法   应用程序在后台运行的情况(不是   由于某种原因,系统需要终止它。

所以你必须在plist文件中将UIApplicationExitsOnSuspend值设置为YES,否则无法保证applicationWillTerminate:将被调用。这就是为什么文档中可能用于。

我不认为会调用过期处理程序块,但我不确定。

答案 2 :(得分:1)

这很容易测试,所以我只是(在运行iOS 6.1.3的iPhone 4S上)使用我最后会粘贴的代码,这会在app delegate的applicationDidEnterBackground方法中启动后台任务。

结果令人惊讶。

当用户通过单击“主页”按钮退出应用程序,然后手动杀死应用程序(通过双击“主页”,将内容置于jiggy模式并点击应用程序的关闭图标),会发生以下情况:

  1. applicationWillTerminate被召唤。
  2. applicationWillTerminate退出时,无论后台任务执行时间多少,后台执行都会终止。该应用程序已被杀死。
  3. <强>无论其..

    如果你安排的事情是applicationWillTerminate在被调用之后没有退出,就像在下面的代码中那样,当我的测试设置出现时,会发生以下情况 - 当手动杀死应用时:

    1. 应用的后台任务继续在后台运行
    2. 即使分配的后台执行时间已过,后台任务也会继续运行,applicationWillTerminate中的代码也会继续运行,直到该方法退出。
    3. 这显然是一个错误 - 你不应该继续永远运行代码 - 我不会依赖它总是工作。但那些一直在使用各种黑客围绕在后台播放音频以保持应用程序存活的人可能想要调查。如果其他人在不同的iOS版本/设备上尝试代码并获得相同的结果,我会感兴趣。

      我的测试项目中AppDelegate.m的代码:

      //
      //  BTAppDelegate.m
      //  BackgroundTest
      //
      //  Created by David Fearon on 07/05/2013.
      //  Copyright (c) 2013 David Fearon. All rights reserved.
      //
      
      #import "BTAppDelegate.h"
      
      @implementation BTAppDelegate
      
      - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
      {
          NSLog(@"application didFinishLaunchingWithOptions called");
          // Override point for customization after application launch.
      
          return YES;
      }
      
      - (void)applicationWillResignActive:(UIApplication *)application
      {
          NSLog(@"applicationWillResignActive: called");
      
      }
      
      - (void)applicationDidEnterBackground:(UIApplication *)application
      {
          NSLog(@"applicationDidEnterBackground: called");
      
      
          UIApplication* thisApp = [UIApplication sharedApplication];
          UIBackgroundTaskIdentifier __block task = [thisApp beginBackgroundTaskWithExpirationHandler:^{
          }];
      
          dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
              [self printTimeRemaining];
              while(YES) {
                  [NSThread sleepForTimeInterval:1.0];
                  [self printTimeRemaining];
              }
              //[thisApp endBackgroundTask:task];
          });
      
      }
      
      
      -(void)printTimeRemaining{
          NSLog(@"Background task time remaining: %f", [[UIApplication sharedApplication] backgroundTimeRemaining]);
      }
      
      - (void)applicationWillEnterForeground:(UIApplication *)application
      {
          NSLog(@"applicationWillEnterForeground: called");
      
      }
      
      - (void)applicationDidBecomeActive:(UIApplication *)application
      {
          NSLog(@"applicationDidBecomeActive: called");
      
      }
      
      - (void)applicationWillTerminate:(UIApplication *)application
      {
          NSLog(@"applicationWillTerminate: called");
      
          while(YES) {
              [NSThread sleepForTimeInterval:1.0];
              NSLog(@"Still executing code in applicationWillTerminate.");
          }
      
      }
      
      @end