一、概览
1.从iOS4.0开始,系统添加了多任务特征,允许应用在按下Home键之后,继续执行后台任务。大部分应用在进入后台之后就进入了挂起状态,只有那些为用户提供重要服务的App能够在进入后台之后继续运行一段时间。
2.一般情况下,我们应该尽可能的避免让我们的应用在进入后台之后继续执行代码。如果必须要执行后台任务,推荐使用以下几种方式:
(1)需要至少实现一种指定的用户服务,这类服务可以获得比较长的后台运行时间。
(2)执行有限时长的任务。
(3)使用本地通知。
二、在执行多任务之前,首先需要判断系统是否支持多任务:
UIDevice* device = [UIDevice currentDevice];
BOOL backgroundSupported = NO;
if ([device respondsToSelector:@selector(isMultitaskingSupported)]){
backgroundSupported = device.multitaskingSupported;
}
三、使用指定的用户服务来启动后台任务:
1.在Info.plist中添加UIBackgroundModes键值,它包含一个或多个string的值,指定App需要的后台服务,如果不指定相关的值,服务将不能在后台执行。
2.可用的后台服务包含一下几个类型:
(1)音频播放服务,对应字符串:audio。
(2)定位服务,对应字符串:location。
(3)基于因特网的电话服务,对应字符串:voip。
(4)Newsstand后台下载服务,对应字符串:newsstand-content。
(5)硬件访问服务,对应字符串:external-accessory。
(6)蓝牙访问服务,对应字符串:bluetooth-central。
(7)外围模式的蓝牙交流服务,对应字符串:bluetooth-peripheral。
3.前面的每一个值都让系统知道,应用需要在合适的时间被唤醒去响应相关的事件。也就是说,添加了对应的字符串值以后,直接使用对应服务的API实现服务即可,后台任务会自动开启;如果没有添加对应的字符串值,即使使用对应的API实现了服务,当应用进入后台状态,服务会立即被终止。
4.每种服务具体的实现方式,可以参考苹果技术文档。
四、执行有限时长的任务
1.当应用进入后台状态之后,可以申请一小段时间来完成任何重要的任务。调用UIApplication的类方法:beginBackgroundTaskWithExpirationHandler,此方法会延迟App进入挂起状态。
2.beginBackgroundTaskWithExpirationHandler方法返回一个后台任务句柄。可以同时启动多个后台任务,每个后台任务都对应一个句柄,可以通过此句柄来判别对应的任务。
3.beginBackgroundTaskWithExpirationHandler该方法的参数是一个block,参数和返回值都为空,当可用的后台运行时间趋近于0时,此block会被调用。在此block中,应该使用endBackgroundTask方法来结束后台任务。如果后台任务终止失败,应用将会被强制关闭。此block在主线程同步调用。
4.每一个beginBackgroundTaskWithExpirationHandler方法,都必须对应一个endBackgroundTask方法。endBackgroundTask方法可以在非主线程安全的调用。
5.当后台任务代码执行完毕之后,也需要实时的结束后台任务。
6.结束后台任务的规则:首先检查任务句柄是不是等于UIBackgroundTaskInvalid,如果不等于,调用endBackgroundTask,然后将任务句柄赋值为:UIBackgroundTaskInvalid。
7.通过UIApplication的backgroundTimeRemaining属性,可以获知还有剩余多少后台运行时间。
8.示例代码:
-(void)applicationDidEnterBackground:(UIApplication *)application{
//申请后台运行时间
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
//清理没完成的任务
xxxxxxxxxxxxxxxxxxxxxx
//结束任务
if(bgTask != UIBackgroundTaskInvalid){
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
}];
//开始执行任务,
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//执行必要的任务,以同步代码的方式。
xxxxxxxxxxxxxxxx
//结束任务
if(bgTask != UIBackgroundTaskInvalid){
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
}
五、本地通知
本地通知在"iOS中通知的使用"章节有介绍,在这里就不说了。