iOS随记

iOS如何防止APP退到后台被kill掉

2020-03-04  本文已影响0人  脚踏实地的小C

  自从iOS更新到13的系统后,说实在不被人吐槽是不可能的,比如我用UC浏览器好好地看一小说,暂时去回复下微信,返回浏览器,MMP的,APP一退到后台就被终止,只得重启了,心里那个气啊。

那么问题来了,为什么APP进入后台,会被系统KILL掉呢?

  当APP进入后台,此时的APP所占用的内存就不是由我们自己控制,而是由系统去控制。当系统认为其他应用需要占用内存时,系统会优先把进入后台的APP Kill掉,进而释放内存供其他应用使用。

在网上搜索了一些资料,有两种方式:

1、当APP进入后台时,持续进行定位操作,并且要告知系统,我当前仍然有操作未完成;
2、当APP进入后台,循环播放无声应约。

然而我这边试了,没起什么作用。这个是传送门,你们可以试试看。

下面为楼主 亲测有效 的一种方法:

static BOOL goingToQuit = NO;
//自定义停留时间
#define KILL_IN_BACKGROUND_AFTER_SECS 3600
- (void)applicationDidEnterBackground:(UIApplication *)application{
    goingToQuit = YES;
    
    UIApplication* app = [UIApplication sharedApplication];
    UIBackgroundTaskIdentifier __block bgTask;//设置后台任务ID
    //开始申请一些额外的时间来处理任务,延迟系统挂起你的应用
    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
      //退到后台后30秒进入
      [app endBackgroundTask:bgTask];//告诉系统,任务完成了,可以挂起APP了
      bgTask = UIBackgroundTaskInvalid;
    }];

    if(UIBackgroundTaskInvalid != bgTask) {
      // Start the long-running task to kill app after some secs and return immediately.
      dispatch_after( dispatch_time(DISPATCH_TIME_NOW, KILL_IN_BACKGROUND_AFTER_SECS * 1e09),
        dispatch_get_main_queue(), ^{
          if(goingToQuit) exit(0);
          [app endBackgroundTask: bgTask];
        });
    }
}

看到这,你可能会想为什么呢?原理是什么呢?

  首先呢,我们通过调用 beginBackgroundTaskWithExpirationHandler:(或者beginBackgroundTaskWithName:expirationHandler:) 来向系统申请一些额外的时间来处理任务,暂延系统挂起你的应用。当完成任务后,必须 调用 endBackgroundTask:(系统默认30秒就会进入beginBackgroundTaskWithExpirationHandler:的回调当中) 方法来告诉系统任务完成了,可以 挂起 应用了。
  注意:如果调用 endBackgroundTask:失败,将会导致你的应用被终止。所以我们在启动任务的时候提供了一个过期处理(dispatch_after( dispatch_time(DISPATCH_TIME_NOW, KILL_IN_BACKGROUND_AFTER_SECS * 1e09), dispatch_get_main_queue(), ^{})),系统就会调用这个处理,这是系统给我们的最后一次机会来避免应用终止。

小结:

1、beginBackgroundTaskWithExpirationHandler:endBackgroundTask:一定要成对使用,不可或缺。
2、我们为了避免程序调用endBackgroundTask:失败,一定要加个 过期处理,不怕一万,就怕万一,你说是不。

参考文献:
APP Run In Background浅析(App 的后台运行)

上一篇 下一篇

猜你喜欢

热点阅读