NSURLSession的工作流程

NSURLSession是iOS7中新的网络接口,它与咱们熟悉的NSURLConnection是并列的。在程序在前台时,NSURLSession与NSURLConnection可以互为替代工作。注意,如果用户强制将程序关闭,NSURLSession会断掉。

NSURLSession提供的功能:

  • 通过URL将数据下载到内存
  • 通过URL将数据下载到文件系统
  • 将数据上传到指定URL
  • 在后台完成上述功能

 

工作流程

如果我们需要利用NSURLSession进行数据传输我们需要:

  1. 创建一个NSURLSessionConfiguration,用于第二步创建NSSession时设置工作模式和网络设置:

工作模式分为:

  • 一般模式(default):工作模式类似于原来的NSURLConnection,可以使用缓存的Cache,Cookie,鉴权。
  • 及时模式(ephemeral):不使用缓存的Cache,Cookie,鉴权。
  • 后台模式(background):在后台完成上传下载,创建Configuration对象的时候需要给一个NSString的ID用于追踪完成工作的Session是哪一个(后面会讲到)。

网络设置:参考NSURLConnection中的设置项。

  1. 创建一个NSURLSession,系统提供了两个创建方法:

  • sessionWithConfiguration:
  • sessionWithConfiguration:delegate:delegateQueue:

    第一个粒度较低就是根据刚才创建的Configuration创建一个Session,系统默认创建一个新的OperationQueue处理Session的消息。

    第二个粒度比较高,可以设定回调的delegate(注意这个回调delegate会被强引用),并且可以设定delegate在哪个OperationQueue回调,如果我们将其设置为[NSOperationQueue mainQueue]就能在主线程进行回调非常的方便。

  2.创建一个NSURLRequest调用刚才的NSURLSession对象提供的Task函数,创建一个NSURLSessionTask。

  根据职能不同Task有三种子类:

  • NSURLSessionUploadTask:上传用的Task,传完以后不会再下载返回结果;
  • NSURLSessionDownloadTask:下载用的Task;
  • NSURLSessionDataTask:可以上传内容,上传完成后再进行下载。

  得到的Task,调用resume开始工作。

  3. 如果是细粒度的Session调用,Session与Delegate会在指定的OperationQueue中进行交互,以咱们下载例子,交互过程的顺序图如下(假如不需要鉴权,即非HTTPS请求):

 

 

  5. 当不再需要连接调用Session的invalidateAndCancel直接关闭,或者调用finishTasksAndInvalidate等待当前Task结束后关闭。这时Delegate会收到URLSession:didBecomeInvalidWithError:这个事件。Delegate收到这个事件之后会被解引用。

  6. 如果是一个BackgroundSession,在Task执行的时候,用户切到后台,Session会和ApplicationDelegate做交互。当程序切到后台后,在BackgroundSession中的Task还会继续下载,这部分文档叙述比较少,现在分三个场景分析下Session和Application的关系:

  • 当加入了多个Task,程序没有切换到后台。

  这种情况Task会按照NSURLSessionConfiguration的设置正常下载,不会和ApplicationDelegate有交互。

  • 当加入了多个Task,程序切到后台,所有Task都完成下载。

  在切到后台之后,Session的Delegate不会再收到,Task相关的消息,直到所有Task全都完成后,系统会调用ApplicationDelegate的application:handleEventsForBackgroundURLSession:completionHandler:回调,之后“汇报”下载工作,对于每一个后台下载的Task调用Session的Delegate中的URLSession:downloadTask:didFinishDownloadingToURL:(成功的话)和URLSession:task:didCompleteWithError:(成功或者失败都会调用)。

  之后调用Session的Delegate回调URLSessionDidFinishEventsForBackgroundURLSession:。

  注意:在ApplicationDelegate被唤醒后,会有个参数ComplietionHandler,这个参数是个Block,这个参数要在后面Session的Delegate中didFinish的时候调用一下,如下:

@implementation APLAppDelegate

 

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier

  completionHandler:(void (^)())completionHandler

{

    BLog();

    /*

     Store the completion handler. The completion handler is invoked by the view controller's checkForAllDownloadsHavingCompleted method (if all the download tasks have been completed).

     */

      self.backgroundSessionCompletionHandler = completionHandler;

}

//……

@end

 

//Session的Delegate

@implementation APLViewController

 

- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session

{

    APLAppDelegate *appDelegate = (APLAppDelegate *)[[UIApplication sharedApplication] delegate];

    if (appDelegate.backgroundSessionCompletionHandler) {

        void (^completionHandler)() = appDelegate.backgroundSessionCompletionHandler;

        appDelegate.backgroundSessionCompletionHandler = nil;

        completionHandler();

    }

 

    NSLog(@"All tasks are finished");

}

@end

 

  • 当加入了多个Task,程序切到后台,下载完成了几个Task,然后用户又切换到前台。(程序没有退出)

  切到后台之后,Session的Delegate仍然收不到消息。在下载完成几个Task之后再切换到前台,系统会先汇报已经下载完成的Task的情况,然后继续下载没有下载完成的Task,后面的过程同第一种情况。

  • 当加入了多个Task,程序切到后台,几个Task已经完成,但还有Task还没有下载完的时候关掉强制退出程序,然后再进入程序的时候。(程序退出了)

  最后这个情况比较有意思,由于程序已经退出了,后面没有下完Session就不在了后面的Task肯定是失败了。但是已经下载成功的那些Task,新启动的程序也没有听“汇报”的机会了。经过实验发现,这个时候之前在NSURLSessionConfiguration设置的NSString类型的ID起作用了,当ID相同的时候,一旦生成Session对象并设置Delegate,马上可以收到上一次关闭程序之前没有汇报工作的Task的结束情况(成功或者失败)。但是当ID不相同,这些情况就收不到了,因此为了不让自己的消息被别的应用程序收到,或者收到别的应用程序的消息,起见ID还是和程序的Bundle名称绑定上比较好,至少保证唯一性

总结

  就像前面说的,在普通的应用场景下NSURLSession与NSURLConnection相比没有什么优势,但是在程序切换到后台之后Background的Session就显得更加灵活了。

  另外,现在主流的网络开发框架AFNetworking已经更新到了2.0(只支持iOS 6 / iOS 7),其中最重要的一个更新就是添加了NSURLSession相关的支持。虽然就我现在(2013.10.13)看到他们的源码中,还没有完全的支持后台的Session(或者说没有考虑全我上述的后台情况),但是大家有兴趣可以关注一下他们后续的更新情况。


If an iOS app is terminated by the system and relaunched, the app can use the same identifier to create a new configuration object and session and retrieve the status of transfers that were in progress at the time of termination. This behavior applies only for normal termination of the app by the system. If the user terminates the app from the multitasking screen, the system cancels all of the session’s background transfers. In addition, the system does not automatically relaunch apps that were force quit by the user. The user must explicitly relaunch the app before transfers can begin again.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值