iOS 7.0 Background Transfer Service

来源:互联网 发布:js body append 编辑:程序博客网 时间:2024/06/09 23:43

这次在做一个iOS端上的后台上传下载应用,需要将很多图片在后台静默上传到服务器上,等上传完通知用户,这在以前是基本不可能实现的,在iOS 7之后增加了一些后台的API,通过其中的background transfer service就可以实现了。

其中发现一些需要注意的点,记录下来。

1. 首先,通过backgroundSessionConfiguration创建的,其中的identifier中必须以程序的bundle identifier开头,否则的话,AppDelegate中的handleEventsForBackgroundURLSession是不会被调用的,这一点在文档中并没有被提及,是经过尝试才发现的。

2. 其次,加入这个service的task还是有可能被取消的,取消之后,当程序重新运行的时候会调用NSURLSession的delegate中的didCompleteWithError回调,取消的原因会在NSURLErrorBackgroundTaskCancelledReasonKey中给出,目前有两种原因,一种是用户强制关闭了这个应用,一种是这个service被禁用了(目前还不知道如何禁用它)

3. 会有以下五种情况需要考虑,参考了这篇文章,可以详细知道AppDelegate和NSURLSession的delegate都分别会在何时被调用,首先需要了解在iOS中,程序会处于以下一些状态:不在运行,正在运行,后台(正在执行代码),后台(未在执行代码)。其中不在运行可以是系统杀死或者用户强制杀死应用。

  • 有多个Task被加入,但是程序一直在运行,从来没有被切换到后台,那么AppDelegate不会收到回调,didCompleteWithError会陆续被调用
  • 当加入了多个Task,程序切到后台,所有Task都完成下载。这个时候AppDelegate的handle函数会被调用,然后针对每一个task,会调用一次didCompleteWithError,同时最后调用一次Session的Delegate回调URLSessionDidFinishEventsForBackgroundURLSession,注意,在完成所有任务之后,需要调用一次AppDelegate中的那个completeHandler
  • 当加入了多个Task,程序切到后台,下载完成了几个Task,然后用户又切换到前台。(程序没有退出)。这个时候,AppDelegate不会被调用,针对每个task,会调用一次didCompleteWithError,之后情况就回归了最初始的状态,只是task少了一些而已。根据用户的行为,会继续发生这里四种情况。
  • 当程序切到后台之后,由于内存或其他原因,程序被系统关闭,那么当所有Task完成之后,系统会重新启动应用,并参照第二种情况进行汇报。
  • 加入多个Task,程序切到后台,还有未完成的Task,用户强制退出的程序。这个时候,任何回调都不会被调用,实际上,所有未完成的Task都已经被取消掉了。直到用户重新启动程序之后,我们可以使用之前创建configuration时候的identifier重新关联到之前的那个URLSession,这个时候,系统会逐一调用didCompleteWithError汇报每一个Task的状态(成功、失败和取消)。


最开始我尝试使用了AFNetworking,但是发现无法适应第四种和第五种情况,因为一旦Session有了delegate之后,会马上调用delegate的这些函数,而session是在manager的init函数中被创建的,会导致我们无法收到之前程序被关闭,同时AFNetworking的manager也无法在程序被系统或者用户杀死之后保留之前的那些Task,导致manager无法正确调用对应的completehandler,使得我们的程序无法知道这些情况。所以在AFNetworking作出改变之前,我们只能通过直接使用NSURLSession来进行这些操作,才能实现真正的后台下载和上传。

0 0
原创粉丝点击