iOS7以前的Multitasking
iOS的多任务是在iOS4的时候被引入的,在此之前iOS的app都是按下Home键就被干掉了。iOS4虽然引入了后台和多任务,但是实际上是伪多任务,一般的app后台并不能执行自己的代码,只有少数几类服务在通过注册后可以真正在后台运行,并且在提交到AppStore的时候也会被严格审核是否有越权行为,这种限制主要是出于对于设备的续航和安全两方面进行的考虑。之后经过iOS5和6的逐渐发展,后台能运行的服务的种类虽然出现了增加,但是iOS后台的本质并没有变化。在iOS7之前,系统所接受的应用多任务可以大致分为几种:
后台完成某些花费时间的特定任务
后台播放音乐等
位置服务
IP电话(VoIP)
Newsstand
在WWDC 2013的keynote上,iOS7的后台多任务改进被专门拿出来向开发者进行了介绍,到底iOS7里多任务方面有什么新的特性可以利用,如何使用呢?简单来说,iOS7在后台特性方面有很大改进,不仅改变了以往的一些后台任务处理方式,还加入了全新的后台模式,本文将针对iOS7中新的后台特性进行一些学习和记录。大体来说,iOS7后台的变化在于以下四点:
- 改变了后台任务的运行方式
- 增加了后台获取(Background Fetch)
- 增加了推送唤醒(静默推送,Silent Remote Notifications)
- 增加了后台传输(Background Transfer Service)
iOS7的多任务
后台任务
首先看看后台任务的变化,先说这方面的改变,而不是直接介绍新的API,是因为这个改变很典型地代表了iOS7在后台任务管理和能耗控制上的大体思路。从上古时期开始(其实也就4.0),UIApplication提供了-beginBackgroundTaskWithExpirationHandler:方法来使app在被切到后台后仍然能保持运行一段时间,app可以用这个方法来确保一些很重很慢的工作可以在急不可耐的用户将你的应用扔到后台后还能完成,比如编码视频,上传下载某些重要文件或者是完成某些数据库操作等,虽然时间不长,但在大多数情况下勉强够用。如果你之前没有使用过这个API的话,它使用起来大概是长这个样子的:
(void) doUpdate
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self beginBackgroundUpdateTask]; NSURLResponse * response = nil; NSError * error = nil; NSData * responseData = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error]; // Do something with the result [self endBackgroundUpdateTask];
});
}(void) beginBackgroundUpdateTask
{
self.backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUpdateTask];
}];
}(void) endBackgroundUpdateTask
{
[[UIApplication sharedApplication] endBackgroundTask: self.backgroundUpdateTask];
self.backgroundUpdateTask = UIBackgroundTaskInvalid;
}
在beginBackgroundTaskWithExpirationHandler:里写一个超时处理(系统只给app分配了一定时间来进行后台任务,超时之前会调用这个block),然后进行开始进行后台任务处理,在任务结束或者过期的时候call一下endBackgroundTask:使之与begin方法配对(否则你的app在后台任务超时的时候会被杀掉)。同时,你可以使用UIApplication实例的backgroundTimeRemaining属性来获取剩余的后台执行时间。
具体的执行时间来说,在iOS6和之前的系统中,系统在用户退出应用后,如果应用正在执行后台任务的话,系统会保持活跃状态直到后台任务完成或者是超时以后,才会进入真正的低功耗休眠状态。