iOS申请持续的后台时间

iOS申请持续的后台时间

xcode

 安全

因为苹果的后台机制,当咱们按下home键的时候,全部线程包括主线程的任务都会被挂起,一些资源好比socket也会被系统回收,会致使不少问题,好比一个很重要的资源中断下载,或者定时器方法被暂停等等。服务器

 

苹果在4.0之后提供了一种申请后台时间的机制:app


- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void (^)(void))handlersocket

声明:async

标记要开始一个新的长期运行的后台任务函数

 

参数:
handler oop

应用程序后台剩余时间快到达为0的时候的一个处理回调,你应该使用这个回调来作一些清理工做和后台任务结束的标记,未能明确地结束任务将致使APP的终止,这个处理回调将在主线程中被同步调用,并马上阻止app的暂停当app被通知的时候。
spa


返回值:.net

一个新的后台任务的惟一的标示符,你必须将这个值传给endBackgroundTask:方法来标记任务的结束。若是没法在后台运行这个方法将返回UIBackgroundTaskInvalid。

 

描述:

这个方法会让你的app转到后台之后继续运行一段时间,你能够在一个任务未完成将会致使影响用户体验的状况下调用此方法。例如,你能够调用次方法来获取足够的时间来传输一个很重要的文件到远程服务器或者至少尝试标记一些错误。你不该该随意的调用这个方法来保持你的app在后台长期运行。

 

每一次调用此方法都应该有对应的endBackgroundTask:方法,app的后台运行时间是有限的(你能够经过backgroundTimeRemaining属性来获取这个可用时间)若是在这个时间耗尽以前你没有调用endBackgroundTask:方法来结束相应的每一个后台任务,系统就会杀掉这个app。若是你提供了这个handler,系统将会在到期时间到达以前调用这个handler来给你这个机会来终止你的任务。

 

你能够在你应用程序执行的任何地方调用这个方法,你也能够屡次调用这个方法来标记多个并行的后台任务,然而,每一个任务必须分开终止,你能够经过这个方法的返回值来标记不一样的任务。

 

为了便于调试,这个方法是基于调用函数或者方法的名称来为任务命名的,若是你须要自定义这个名称,可使用beginBackgroundTaskWithName:expirationHandler:方法来代替。

 

这个方法能够在非主线程中安全调用。

注意:

若是你在调试后台任务遇到麻烦,你能够尝试使用beginBackgroundTaskWithName:expirationHandler:方法太替代这个方法,这个方法提供相同的功能可是能够给你一个调试可用的任务名称。

 

使用方法:

如下在子线程中打开一个定时器,并在应用程序进入到后台之后打开回调

 

[objc]  view plain  copy
  1. [[NSNotificationCenter defaultCenter]  addObserver:self selector:@selector(applicationDidEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];  
  2.   
  3. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  
  4.       
  5.     NSTimer* timer = [NSTimer timerWithTimeInterval:10.0  
  6.                                              target:self  
  7.                                            selector:@selector(timerHandle)  
  8.                                            userInfo:nil  
  9.                                             repeats:YES];  
  10.       
  11.     [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];  
  12.       
  13.     [[NSRunLoop currentRunLoop]run];  
  14.       
  15.     });  

 

 

如下回调方法是申请后台时间,当系统没法再给更多的时间的时候会调用handler中的block块,在这个block中,咱们要作相应的清理工做并终止后台任务(备注:若是咱们不调用endBackgroundTask:来终止相应的后台任务的话,好像还能继续运行后台任务,不知道为啥,苹果文档是说你不本身终止,系统会给你kill掉)

 

[objc]  view plain  copy
  1. -(void)applicationDidEnterBackground  
  2. {  
  3.     UIApplication*  application = [UIApplication sharedApplication];  
  4.   
  5.     bgTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^{  
  6.           
  7.         NSLog(@"Starting background task with %f seconds remaining", application.backgroundTimeRemaining);  
  8.           
  9.         if (bgTaskIdentifier != UIBackgroundTaskInvalid)  
  10.         {  
  11.             [application endBackgroundTask:bgTaskIdentifier];  
  12.             bgTaskIdentifier = UIBackgroundTaskInvalid;  
  13.         }  
  14.     }];  
  15. }  

[objc]  view plain  copy
  1. - (void)timerHandle  
  2. {  
  3.     NSLog(@"timerHandle");  
  4.       
  5. }  

 

我在子线程中开启了一个定时器,每隔10秒打印一次timerHandle,我在应用程序进入到后台之后申请了更多的后台时间,所以,当我按下home或者锁屏的时候,定时器方法会继续调用。

 

咱们把定时器方法修改以下:

 

[objc]  view plain  copy
  1. - (void)timerHandle  
  2. {  
  3.     NSLog(@"timerHandle");  
  4.       
  5.     UIApplication*  application = [UIApplication sharedApplication];  
  6.       
  7.     if (bgTaskIdentifier != UIBackgroundTaskInvalid)  
  8.     {  
  9.         [application endBackgroundTask:bgTaskIdentifier];  
  10.         bgTaskIdentifier = UIBackgroundTaskInvalid;  
  11.     }  
  12. }  

 

当定时器一启动咱们就按下home键,在第一个10秒会打印timerHandle,而后应用程序会终止后台任务,直到咱们从新进入到前台,才会继续打印信息。

 

同理,若是我此时是在后台下载文件,完成之后应该经过以上方法来终止相应的后台任务,按照苹果文档说的不能什么事情也没干还让程序在后台运行,

 

以上的bgTaskIdentifier是全局的UIBackgroundTaskIdentifier型变量,用来标示不一样的后台任务的。好比说我有一个定时器须要后台运行,还有一个文件须要后台下载,那么咱们就要经过这个不一样的标示符来分开申请后台时间,并在后台完成任务之后分别去终止相应地后台任务。

相关文章
相关标签/搜索