IOS 后台运行申请更多的时间

  当应用程序进入后台时,系统会自动回调应用程序委托的applicationDidEnterBackground:方法。

应用能够在该方法中完成转入后台前须要作的准备工做,全部的应用须要作如下事情。并发

  释放全部能够释放的内存。app

  保存用户数据或状态信息,全部没写入磁盘的文件或信息,在进入后台以前,都应该写入磁盘,由于程序可能在后台被杀死。异步

进入后台时释放内存

    当程序进入后台以后,为了确保得到最佳的用户体验,建议释放那些占用内存较大且能够从新获取的资源—-async

这是由于当应用处于后台时,iOS系统会优先终止那些占用内存大的应用。若是应用尽量释放其所占用的内存,spa

那么应用就能够在后台存或更久。从这个角度来看,能够获得一个结论:应用暂停时所占用的内存减小,iOS完全终止该应用的风险就越低。线程

若是应用没有启用ARC机制,程序须要在应用进入后台时,将那些须要释放的资源的引用计数变为0,从而让系统回收这些资源。server

当应用转入前台时,系统须要从新恢复这些资源。对象

若是应用启用了ARC机制,程序只要在应用进入后台时,将应用那些须要释放的资源的变量赋为nil便可。当应用转入前台时,队列

系统须要从新恢复这些资源。图片

//  使用默认的通知中心监听应用转入前台的过程

//  应用转入前台时会向通知中心发送UIApplicationWillEnterForegroundNotification

//  从而激发enterFore:方法

[[NSNotificationCenter defaultCenter] addObserver:self  selector:@selector:@selector(enterBack:) name:UIApplicationWillEnterForegroundNotification

object:[UIApplication sharedApplication]];

//  使用默认的通知中心监听应用转入前台的过程

//  应用转入前台时会向通知中心发送UIApplicationDidEnterBackgroundNotification

//  从而激发enterFore:方法

[[NSNotificationCenter defaultCenter] addObserver:self  selector:@selector:@selector(enterBack:) name:UIApplicationDidEnterBackgroundNotification

object:[UIApplication sharedApplication]];

说明

上面程序控制当应用转入前台时,该视图控制器的enterFore:方法被调用;当应用转入后台时,该控制器的enterBack:方法被调用,下面是enterBack:方法的代码

 

- (void) enterBack:(NSNotification *)notification

{

   NSLog(@”—enterBack—”);

   // 转入后台时将能够迅速重建,并且占用内存较大的对象设为nil,以便系统释放内存  

bgLayer1.contents = nil;

bgLayer2.contents = nil;

ePlaneImage1 = nil;

}

说明

 因为该应用已经启用了ARC机制,所以上面方法只要将这些图片、音乐资源的变量设为nil,系统就能够回收这些图片、音乐资源所占用的内存。

    当应用再次转入前台时,该控制器的enterFore:方法被调用,该方法将负责再次加载这些图片、音乐资源。下面是enterFore:方法的代码。

代码片断

-  (void) enterFore:(NSNotification *)notification

{

    NSLog(@”===enterFore===”);

bgLayer1.contents = (id)[bgImage CGImage];

bgLayer2.contents = (id)[bgImage CGImage];

ePlaneImage1 = [UIImage imageNamed:@”e1”];

}

说明

  经过上面的处理方法,程序能够在应用转入后台时释放大部份内存,使得该应用在后台以少许内存运行,从而下降该应用被iOS系统终止的风险。当该应用转入前台时,系统将会再次初始化 这些资源,从而保证iOS应用能够迅速恢复。

进入后台时保存状态

当应用进入后台时,若是程序有一些状态数据没有保存,而iOS系统可能在内存紧张时终止该应用,那么就可能致使该应用丢失这些状态数据。

为了让应用不会丢失状态数据,程序能够在应用转入后台时记录应用状态,应用转入后台时将会调用视图控制器的enterBack:方法,所以在该方法后面增长以下代码:

     // 使用NSUserDefaults存储系统积分

   [[NSUserDefaults standardUserDefaults] setInteger:score forkey:@”score”];

    上面的代码只是简单地使用了NSUserDefault来保存程序状态。若是程序须要保存的状态数据较多,也可采用plist属性文件或者其余形式来保存程序状态。

     接下来一样能够在应用转入前台时恢复程序状态,应用转入前台时将会调用视图控制器的enterFore:方法,所以在该方法后面增长以下代码:

  // 使用NSUserDefaults读取系统已经保存的积分

  NSNumber* scoreNumber;

  if((scoreNumber = [[NSUserDefault standardUserDefaults]

objectForKey:@”score”]))

{

    score = scoreNumber.integerValue;

}

请求更多的后台时间

   当应用转入后台后,不要在主线程中执行超过5秒的任务,若是应用进入后台花费了太多时间(即applicationDidEnterBackground:方法的执行体花费太多时间),应用可能从内存中被删除.

   假如应用程序正在执行文件下载或文件传输等,当应用进入后台时,若是该任务尚未执行完成,应用转入后台该任务就会被暂停.千万不要强制在applicationDidEnterBackground:方法中直接完成该任务—-由于这会致使应用进入后台花费太多时间,iOS系统可能直接从内存中删除该应用.正确的作法是: 以applicationDidEnterBackground:方法为平台,告诉系统进入后台仍是更多的任务须要完成,从而向系统申请更多的后台时间.在这种方式下,当咱们的应用处于后台时,即便用户正在使用其余应用,只要系统仍是足够的内存,咱们的应用就能够保存在内存中,iOS系统会保留应用运行一段时间。

为了请求更多的后台时间,按以下步骤执行:

1.调用UIApplication对象的beginBackgroundTaskWithExpirationHandler:方法请求获取更多的后台执行时间,该方法默认请求额外得到10分钟后台时间。该方法须要传入一个代码块做为参数,若是请求获取后台执行时间失败,将会执行该代码块。该变量可做为后台任务的标识符。

2.调用dispatch_async()方法将指定代码块提交给后台执行.

3.后台任务执行完成时,调用UIApplication对象的endBackgroundTask:方法结束后台任务

  例如以下示例应用,该应用在系统转入后台时请求了后台执行时间,而后启动一个代码块,该代码块循环100次,模拟执行一个耗时的下载任务.从该程序转入后台的执行过程能够看出,经过这种机制便可让iOS应用在后台执行更长时间.

下面是该应用的视图控制器类的实现部分代码

ViewController.m

@implementation ViewController

- (void)viewDidLoad

{

   [super viewDidLoad];

   // 使用默认的通知中心监听应用转入后台的过程

   //  应用转入后台时会向通知中心发送UIApplicationDidEnterBackgroundNotification

   // 从而激发enterBack:方法

   [[NSNotificationCenter defaultCenter]  addObserve:self

selector:@selector(enterBack:)

name:UIApplicationDidEnterBackgroundNotification

object:[UIApplication sharedApplication]];

}

- (void)enterBack:(NSNotification *)notification

{

   UIApplication *app = [UIApplication sharedApplication];

   // 定义一个UIBackgroundTaskIdentifier类型(本质就是NSUInteger)的变量

   // 该变量将做为后台任务的标识符

   __block UIBackgroundTaskIdentifier backTaskId;

   backTaskId = [app beginBackgroundTaskWithExpirationHandler:^

{

      NSLog(@”===在额外申请的10分钟内依然没有完成任务===”);

      // 结束后台任务

     [app endBackgroundTask:backTaskId];

}];

 if(backTaskId == UIBackgroundTaskInvalid)

{

   NSLog(@”===iOS版本不支持后台运行,后台任务启动失败===”);

   return;

}

// 将代码块以异步方式提交给系统的全局并发队列

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

, ^{

    NSLog(@”===额外申请的后台任务时间为: %f===”

,  app.backgroundTimeRemaining);

// 其余内存清理的代码也能够在此处完成

for(int i = 0 ; i < 100 ; i++)

{

     NSLog(@”下载任务完成了%d%%” , i);// 转换成百分比

// 暂停10秒模拟正在执行后台下载

[NSThread sleepForTimeInterval:10];

}

NSLog(@”===剩余的后台任务时间为: %f===”

,  app.backgroundTimeRemaining);

// 结束后台任务

[app endBackgroundTask:backTaskId];

});

}

@end

相关文章
相关标签/搜索