NSURLSession类和相关的类提供很多API来下载HTTP的内容。这些API提供多种delegate协议来支持验证和执行后台下载任务。

1 URL Session 设计概念

Session中的任务行为依赖三件事:

  • Session类型:在创建时,由configuration 对象决定;
  • task类型:数据传输类型;
  • session执行方式:有前台和后台两种方式。

1.1 Session类型(3种)

    NSURLSession API提供三种类型的session,而这三种类型是在创建时由configuration对象决定:

      1) Default sessions(默认模式):工作模式类似于原来的NSURLConnection,可以使用缓存的Cache,Cookie,鉴权;

      2) Ephemeral sessions(及时模式):不能存储数据到磁盘,包括缓存的Cache,Cookie,鉴权;

      3) Background sessions(后台模式):类似default模式,不同的是后台模式是拥有独立的进程来完成所有数据的传输。

1.2 Task类型(3种)

对于一个session,NSURLSession类支持三种任务类型:

         1) Data任务:该任务是通过NSData对象来发送和接收,其目的经常是向服务器发送请求。

         2) Download任务:该任务是以文件的形式查询数据,并且支持app不在运行状态时,在后台状态进行下载。

         3) Upload任务:该任务是以文件的形式发送数据,并且支持app不在运行状态时,在后台进行上传。

1.3 后台传输设计

session还支持进行后台数据传输功能。但这种功能需要在创建session进行指定,同时它还有如下的限制:

  • session必须提供delegate来响应事件;
  • 仅支持HTTP和HTTPS协议,不支持自定义协议;
  • 仅支持上传文件,而上传对象和字节流将在app退出时发送上传失败;
  • 如果后台传输任务是app在后台进行初始化的,那么需要将configuration对象的configuration属性设置为true。

      在IOS中,当后台任务传输完成或是需要认证,如果此时app不处于运行状态,那么IOS将自动重新启动该app程序,其中IOS将调用UIApplicationDelegate对象的application:handleEventsForBackgroundURLSession:completionHandler方法。

2 第一个程序

2.1 NSURLSession使用步骤

使用NSURLSession类来请求数据,可以按如下步骤进行:

      a) 创建configuration对象,指定session需要的属性;

      b) 创建session对象,并指定相应的configuration对象、选项和delegate对象

     c) 创建task对象,通过调用session相应的请求方法而创建,其中创建的task对象可以是NSURLSessionTask—NSURLSessionDataTask, NSURLSessionUploadTask, 或NSURLSessionDownloadTask的子类。

每个task对象在创建后都初始化为suspended状态,需要手动调用task对象resume方法开始任务处理。

2.2 Xcode环境配置

  1. 打开 工程主目录下info.plist
  2. 增加属性字典 App Transport Security Settings
  3. 在这个属性下增加节点 Allow Arbitrary Loads, value 为 YES

图 1

2.3 源码说明

源码:Object-C

 1 -(void) main
 2 {
 3     NSURLSession *session = [NSURLSession sharedSession];     //创建一个NSURLSession 对象
 4     NSURL *url = [NSURL URLWithString:@"http://baidu.com"];   //创建一个URL连接
 5     NSURLRequest *request = [NSURLRequest requestWithURL: url]; //创建请求对象
 6 
 7     //创建任务
 8     NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
 9         
10         NSString *string = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
11 
12         NSLog(string);   
13     }];
14     
15     [task resume];    //启动任务,即向服务器发送请求。
16 }
17 输出:
18 <html>
19 <meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
20 </html>

3 创建session

3.1 配置(NSURLSessionConfiguration)

session的行为是由NSURLSessionConfiguration对象来指定的,因为session由三种类型,所以NSURLSessionConfiguration类就有三种初始化函数来创建三种类型的对象。

如下是初始化函数的声明:

+ (NSURLSessionConfiguration *)defaultSessionConfiguration;

+ (NSURLSessionConfiguration*)ephemeralSessionConfiguration;

+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier

3.2 创建(NSURLSession)

创建一个NSURLSession,系统提供了三个创建方法:

+ (NSURLSession *)sharedSession;

+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;

+(NSURLSession*)sessionWithConfiguration:(NSURLSessionConfiguration*)configuration delegate: (id <NSURLSessionDelegate>)delegate delegateQueue:(NSOperationQueue *)queue;

  • 第一个是提供默认的session,不要配置;
  • 第二个是使用粒度较低的configuration对象进行创建,系统默认创建一个新的OperationQueue处理Session的消息;
  • 第三个同样使用configuration对象进行创建,同时可以设定回调的delegate(注意这个回调delegate会被强引用),并且可以设定delegate在哪个OperationQueue回调,如果我们将其设置为[NSOperationQueue mainQueue]就能在主线程进行回调非常的方便。

如下例子:

1 /* Create some configuration objects. */
2     NSURLSessionConfiguration *backgroundConfigObject = [NSURLSessionConfiguration backgroundSessionConfiguration: @"myBackgroundSessionIdentifier"];
3     NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
4     NSURLSessionConfiguration *ephemeralConfigObject = [NSURLSessionConfiguration ephemeralSessionConfiguration];

6 /* Create a session for each configurations. */
7     NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
8    NSURLSession *backgroundSession = [NSURLSession sessionWithConfiguration: backgroundConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
9    NSURLSession *ephemeralSession = [NSURLSession sessionWithConfiguration: ephemeralConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];

4 创建task

在NSURLSession API中,实现与服务器进行数据的交互是通过Task(任务)完成,即Task有data、Download和upload类型。

4.1 直接请求

直接请求方式是指可以简单调用NSURLSession指定的方法进行数据下载或上传,而无需再实现Delegate协议,因为IOS框架默认已经帮忙实现了Delegate协议。

由于NSURLSession有三种Task类型:data任务、upload任务和download任务,并且三种任务都是异步执行的。所以提供三种类型的交互方法,其中每种方式都是使用异步方法,当任务完成后,调用相应的回调函数。

表 11 三种任务类型创建方法

Task类型

方法

语义

Data Tasks

- dataTaskWithURL:

创建一个GET方法的HTTP请求,请求的地址由URL参数指定。

- dataTaskWithURL:completionHandler:

这也是创建一个GET请求,但是当请求完成后,会调用completionHandler函数块。

- dataTaskWithRequest:

创建一个HTTP请求,请求的其它更多参数可以由NSMutableURLRequest对象指定,HTTP请求的method、timeoutInterval和URL等信息。

- dataTaskWithRequest:completionHandler:

类似上述方法,不同的是有完成回调函数。

Download Tasks

- downloadTaskWithURL:

创建一个下载url路径的任务

- downloadTaskWithURL:completionHandler:

- downloadTaskWithRequest:

创建一个下载NSURLRequest 的任务

- downloadTaskWithRequest:completionHandler:

- downloadTaskWithResumeData:

创建一个下载NSData的任务

- downloadTaskWithResumeData:completionHandler:

Upload Tasks

- uploadTaskWithRequest:fromData:

创建一个由NSURLRequest指定的上传任务,所上传的数据存放在 NSData对象中

- uploadTaskWithRequest:fromData:completionHandler:

- uploadTaskWithRequest:fromFile:

创建一个由NSURLRequest指定的上传任务,所上传的数据存放在 NSURL路径中

- uploadTaskWithRequest:fromFile: completionHandler:

- uploadTaskWithStreamedRequest:

创建一个由NSURLRequest指定的上传任务,所上传的数据由如下的委托方法提供:URLSession:task:needNewBodyStream:

注意:使用系统提供的默认delegete,进行下载和上传功能是受限制的。

如:

 1 -(void) system_provided_delegates
 2 {
 3     NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
 4     NSURLSession *delegateFreeSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];
 5     
 6     NSURLSessionDataTask *task = [delegateFreeSession dataTaskWithURL: [NSURL URLWithString: @"http://www.example.com/"]
 7                         completionHandler:^(NSData *data, NSURLResponse *response,
 8                                             NSError *error) {
 9                             NSLog(@"Got response %@ with error %@.\n", response, error);
10                         }] ;
11     [task resume];
12 }
 

4.2 委托请求

由于使用系统默认的Delegate方式,进行下载和上传只能控制部分内容,若需要对任务进行更多的控制,则需要实现自定义Delegate。如果使用自定义的Delegate对象来处理数据,那么与服务器的交互都可以在Delegate协议方法内完成。其中NSURLSession提供的Delegate协议有四个:

表 12

协议

功能

NSURLSessionDelegate

定义了session级别的事件;

NSURLSessionTaskDelegate

定义了一些方法来操作task级别的事件包括所有的 task类型

NSURLSessionDataDelegate

定义了一些方法来操作task级别事件,特别是data 和upload 任务

NSURLSessionDownloadDelegate

定义了一些方法来操作task级别事件,特别是download 任务

那么至少需要实现NSURLSessionDataDelegate协议如下的两个方法:

  • URLSession:dataTask:didReceiveData: 告诉delegate已经接收了一部分数据;
  • URLSession:task:didCompleteWithError:告诉delegate已经完成了数据传输任务。

如下是实现了自定定义delegate协议的类:

 1 @interface sesionCustomDelegate : NSURLSession <NSURLSessionDataDelegate>
 2 -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error;
 3 -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data;
 4 @end
 5 @implementation sesionCustomDelegate
 6 -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
 7 {
 8     printf("didCompleteWithError\n");
 9 }
10 -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
11 {
12     printf("didReceiveData\n");
13 }
14 @end
 

如下是自定义类的使用方式:

 1 -(void) Fetching_custom_delegate
 2 {
 3     sesionCustomDelegate *customSession = [[sesionCustomDelegate alloc] init];
 4 NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
 5 
 6     NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject  delegate: customSession delegateQueue: [NSOperationQueue mainQueue]];
 7     
 8     NSURL *url = [NSURL URLWithString: @"http://www.example.com/"];
 9     NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithURL: url];
10     
11     [dataTask resume];
12 }

4.3 开始任务

通过调用NSURLSession 对象来创建任务后,将返回NSURLSessionTask对象或者其子类(NSURLSessionDataTask, NSURLSessionUploadTask, 和NSURLSessionDownloadTask ),此时的NSURLSessionTask对象还处于挂起状态,需要手动调用其resume方法来启动任务,在调用resume方法后立即返回,即不需等待任务完成。

       其中NSURLSessionTask对象拥有多种状态:RunningSuspendedCancelingCompleted四种状态。

5 Downloading文件

5.1 协议方法

在高层级别上,下载数据与请求数据类似,应用程序中应该实现NSURLSessionDownloadDelegate协议的如下方法:

  • URLSession:downloadTask:didFinishDownloadingToURL: 通知下载任务已经完成,其中下载任务只是下载到一个暂时的位置。而在此方法返回之前,需要将该文件移动到一个永久的目录下,或者读起文件的内容。
  • URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite: 用于获取当前下载任务的状态。
  • URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes: 通知app已经将下载失败的任务重启成功,只是通知重新开始下载了,并不是已经下载完成了。
  • URLSession:task:didCompleteWithError: 通知app任务下载失败。

5.2 下载任务

由于app在运行过程中会被挂起、暂停或是退出,那么不同的session模式,对正在下载的任务有不同的处理方式:

  • 如果创建的是后台session,那么当app不在运行状态,那么它将继续下载;
  • 如果创建的标准或是及时session,那么当app重新启动,必须重新开始下载。

上述是IOS强制关闭下载任务的情况,也可以利用NSURLSessionDownloadTask对象NSURLSession对象提供一些功能来手动暂停重启下载任务。

  • cancelByProducingResumeData: 该方法是NSURLSessionDownloadTask类中的方法,通过该方法能够手动暂停正在下载的任务;
  • downloadTaskWithResumeData: 该方法是NSURLSession类中的方法,通过该方法能够重启被暂停的任务。

如下是实现了下载协议的类:

 1 @interface DownloadCustomDelegate : NSObject <NSURLSessionDownloadDelegate>
 2       ……
 3 @end
 4 
 5 @implementation DownloadCustomDelegate 
 6 -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
 7 {
 8     printf("didFinishDownloadingToURL\n");
 9 }
10 
11 -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
12 {
13     NSLog(@"Session %@ download task %@ wrote an additional %lld bytes (total %lld bytes) out of an expected %lld bytes.\n",
14           session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
15 }
16 
17 -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
18 {
19     NSLog(@"Session %@ download task %@ resumed at offset %lld bytes out of an expected %lld bytes.\n",
20           session, downloadTask, fileOffset, expectedTotalBytes);
21 }
22 
23 -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
24 {
25      printf("didCompleteWithError\n");
26 }
27 @end

如下是调用自定义delegate的类:

 1 -(void) Downloading_Files
 2 {
 3     DownloadCustomDelegate *downloadCustomDelegate = [[DownloadCustomDelegate alloc] init];
 4     
 5     NSURLSessionConfiguration *backgroundConfigObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"myBackgroundSessionIdentifier"];
 6     
 7     NSURLSession *backgroundSession = [NSURLSession sessionWithConfiguration: backgroundConfigObject delegate: downloadCustomDelegate delegateQueue: [NSOperationQueue mainQueue]];
 8     
 9     NSURL *url = [NSURL URLWithString: @"https://developer.apple.com/library/ios/documentation/Cocoa/Reference/"
10                   "Foundation/ObjC_classic/FoundationObjC.pdf"];
11     
12     NSURLSessionDownloadTask *downloadTask = [backgroundSession downloadTaskWithURL: url];
13     [downloadTask resume];
14 }

6 Uploading内容

应用程序可以通过HTTP的POST请求,将数据内容封装在HTTP的请求体中,从而上传到服务器中。其中支持的上传方式有如下三种:

                   1) NSData对象

                   2) File

                   3) Stream

6.1 使用NSData对象

为了将NSData对象上传到服务器,应该调用NSURLSession对象的uploadTaskWithRequest:fromData: 方法或是uploadTaskWithRequest:fromData:completionHandler:方法,从而创建上传任务,并且将NSData对象传递给fromData参数。

6.2 使用File

为了将File上传到服务器,需要调用NSURLSession对象的uploadTaskWithRequest:fromFile: 方法或是 uploadTaskWithRequest:fromFile:completionHandler: 方法,从而创建上传任务,并且给fromFile参数传递是File文件的URL路径。

6.3 使用Stream

同样为了将Stream上传到服务器,需要调用NSURLSession对象的uploadTaskWithStreamedRequest: 方法,从而创建上传任务,而上传的内容是存放在NSURLRequest对象相关的字节流中。

7 参考文献

[1] URL Session programming guide。

iOS 网络编程:NSURLSession的更多相关文章

  1. iOS网络编程模型

    iOS网络编程层次结构也分为三层: Cocoa层:NSURL,Bonjour,Game Kit,WebKit Core Foundation层:基于 C 的 CFNetwork 和 CFNetServ ...

  2. IOS网络编程——第三方类库

    IOS网络编程——第三方类库 目录 概述 ASIHttpRequest AFNetworking 其他 概述 ASIHttpRequest AFNetworking 其他

  3. IOS网络编程:HTTP

    IOS网络编程:HTTP HTTP定义了一种在服务器和客户端之间传递数据的途径. URL定义了一种唯一标示资源在网络中位置的途径. REQUESTS 和 RESPONSES: 客户端先建立一个TCP连 ...

  4. iOS网络编程笔记——Socket编程

    一.什么是Socket通信: Socket是网络上的两个程序,通过一个双向的通信连接,实现数据的交换.这个双向连路的一端称为socket.socket通常用来实现客户方和服务方的连接.socket是T ...

  5. iOS 网络编程模式总结

    IOS 可以采用三类api 接口进行网络编程,根据抽象层次从低到高分别为socket方式.stream方式.url 方式. 一 .socket 方式 IOS 提供的socket 方式的网络编程接口为C ...

  6. iOS网络编程

    今天的重点是UIWebView.NSURLSession.JSon. 网络编程联网准备:1.在Info.plist中添加AppTransportSecurity类型Dictionary:2.在AppT ...

  7. 浅谈iOS网络编程之一入门

    计算机网络,基本上可以抽象是端的通信.实际在通讯中会用到不同的设备,不同的硬件中,为了能友好的传输信息,那么建立一套规范就十分必要了.先来了解一些基本概念 了解网络中传输的都是二进制数据流.  2.了 ...

  8. iOS 网络编程:socket

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  9. ios网络编程(入门级别)-- 基础知识

    在学习ios的过程中,停留在UI控件很长时间,现在正在逐步的接触当中!!!!!!在这个过程中,小编学到了一些关于网络编程知识,并且有感而发,在此分享一下: 关于网络请求的重要性我想不用多说了吧!!!对 ...

  10. iOS:网络编程的第三方框架:AFNetworking、SDWebImage

    网络编程第三方框架:AFNetworking.SDWebImage 介绍:这些框架是开源的,经过前人的封装.改进,成为使用次数很多的一个性能好的源代码框架,只需要将它导入项目中,就可以使用.因此,在做 ...

随机推荐

  1. uc浏览器qq浏览器广告过滤

  2. Problems encountered while deleting resources.

    Error The project was not built due to “Problems encountered while deleting resources.”. Fix the pro ...

  3. POJ1680 Currency Exchange SPFA判正环

    转载来源:優YoU  http://user.qzone.qq.com/289065406/blog/1299337940 提示:关键在于反向利用Bellman-Ford算法 题目大意 有多种汇币,汇 ...

  4. C# 日期转换为中文大写

    /// <summary> /// 日期转换为中文大写 /// </summary> public class UpperConvert { public UpperConve ...

  5. oracle 中v$sqlarea,v$sql,v$session,gv$session,远程连接等问题

    一.分析 (1)使用 least recently used (LRU) algorithm 来管理的,不用的自动踢出,可以使用keep 将需要的语句 保存在 library cache中. 所以应该 ...

  6. makefile for VCS from Syn@psys

    已调试通过 未来将修改成verdi的FSDB版本 下载后把 Makefile_VCS.txt 修改为 Makefile 就可以使用 链接地址: http://files.cnblogs.com/all ...

  7. Hadoop学习记录(5)|集群搭建|节点动态添加删除

    集群概念 计算机集群是一种计算机系统,通过一组松散继承的计算机软件或硬件连接连接起来高度紧密地协作完成计算工作. 集群系统中的单个计算机通常称为节点,通过局域网连接. 集群特点: 1.效率高,通过多态 ...

  8. hadoop入门必备基础知识

    1.对Linux 系统的要求        会基本的命令:        (1)知道root用户        (2)ls命令会查看文件夹内容        (3)cd命令等2.Java 的要求    ...

  9. 分布式定时任务框架比较,spring batch, tbschedule jobserver

    分布式定时任务框架比较,spring batch, tbschedule jobserver | 移动开发参考书 分布式定时任务框架比较,spring batch, tbschedule jobser ...

  10. DATASNAP倒底能承受多大的负载能力

    DATASNAP是针对企业数据中间件市场而推出来的产品,如果在其它领域用它可能就不会合适. DATASNAP通信使用INDY10,INDY是阻塞型SOCKET. 1.如果使用TCP/IP长连接,DAT ...