iOS 网络编程:NSURLSession

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。

时间: 2024-08-13 20:19:25

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

iOS网络编程(六) NSURLSession详解

昨夜浏览Demo的时候,看到别人请求网络数据用的是NSURLSession,当时就在想这里什么,怎么没有用过,引起了我的好奇心,遂去百度-谷歌-官方文档一一查看,有了一定的了解,原来NSURLSession是iOS7中新的网络接口,它与咱们熟悉的NSURLConnection是并列的. 查找资料,写了一个小Demo,大家可以看看,有什么不足的地方,可以留言帮我指出来. // // HMTRootViewController.m // // // Created by HMT on 14-6-7.

IOS网络开发NSURLSession详解(一)概述

原创blog,转载请注明出处blog.csdn.net/hello_hwc 我的IOS-SDK详解专栏,欢迎关注 http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html 前言: 这个IOS网络编程的系列计划6篇文章,NSURLSession3篇(一篇概述,一篇详细阐述三种task和delegate的使用,一篇阐述授权,证书等内容),网络的基础知识两篇(一篇REST API讲解已经写完了,一篇我会把写博客的过程中遇到的概念总结出来

iOS网络编程(7) 第三方开源库-----&gt;AFNetworking

AFNetworking是一个为 iOS 和 Mac OSX 制作的令人愉快的网络库,它建立在URL 装载系统框架的顶层,内置在Cocoa里,扩展了强有力的高级网络抽象.它的模块架构被良好的设计,拥有丰富的功能,因此,使用起来,必定赏心悦目. @原文链接https://github.com/AFNetworking/AFNetworking,我在此基础上了点配置修改 @介绍 1.支持HTTP请求和基于REST的网络服务(包括GET.POST. PUT.DELETE等) 2.支持ARC 3.要求i

iOS网络编程开发—HTTP协议

iOS网络编程开发—HTTP协议 说明:apache tomcat服务器必须占用8080端口 一.URL 1.基本介绍 URL的全称是Uniform Resource Locator(统一资源定位符) 通过1个URL,能找到互联网上唯一的1个资源 URL就是资源的地址.位置,互联网上的每个资源都有一个唯一的URL 2.URL中常见的协议 (1)HTTP 超文本传输协议,访问的是远程的网络资源,格式是http:// http协议是在网络开发中最常用的协议 (2)file 访问的是本地计算机上的资源

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

一.什么是Socket通信: Socket是网络上的两个程序,通过一个双向的通信连接,实现数据的交换.这个双向连路的一端称为socket.socket通常用来实现客户方和服务方的连接.socket是TCP/IP协议的一个十分流行的编程接口.一个socket由一个IP地址和一个端口号唯一确定.TCP/IP协议的传输层又有两种协议:TCP(传输控制协议)和UDP(用户数据报协议).TCP是基于连接的,而UDP是无连接的:TCP对系统资源的要求较多,而UDP少:TCP保证数据的正确性而UDP可能丢包:

iOS网络编程开发GET请求和POST请求

iOS网络编程开发GET请求和POST请求 一.GET请求和POST请求简单说明 创建GET请求 // 1.设置请求路径 NSString *urlStr=[NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text]; NSURL *url=[NSURL URLWithString:urlStr]

iOS网络编程(三) 异步加载及缓存图片----&gt;SDWebImage

@SDWebImage提供一个UIImageView的类别以支持加载来自网络的远程图片.具有缓存管理.异步下载.同一个URL下载次数控制和优化等特征. @SDWebImage的导入1.https://github.com/rs/SDWebImage 下载SDWebImage开源包2.将类包拖入工程,再导入MapKit.framework.ImageIO.framework两个框架3.SDWebImage是支持ARC的,在MRC的工程中要注意,可参考MRC工程配置ARC4.注意:SDWebImag

iOS网络编程开发—JSON和XML数据解析

iOS网络编程开发—JSON解析 一.什么是JSON JSON是一种轻量级的数据格式,一般用于数据交互 服务器返回给客户端的数据,一般都是JSON格式或者XML格式(文件下载除外) JSON的格式很像OC中的字典和数组 {"name" : "jack", "age" : 10} {"names" : ["jack", "rose", "jim"]} 标准JSON格式的

IOS网络编程:HTTP

IOS网络编程:HTTP HTTP定义了一种在服务器和客户端之间传递数据的途径. URL定义了一种唯一标示资源在网络中位置的途径. REQUESTS 和 RESPONSES: 客户端先建立一个TCP连接,然后发送一个请求.服务器受到请求处理后发送一个响应向客户端传递数据.然后客户端可以继续发送请求或者关闭这个TCP连接. HTTPS:在TCP连接建立后,发送请求之前,需要建立一个一个SSL会话. request方法和它们的用途 iOS的NSURLRequest和它的子类NSMutableURLR

iOS网络编程--NSConnection的同步连接与异步连接

1 // 2 // ZFViewController.m 3 // 0628-表单验证 4 // 5 // Created by zfan on 14-6-28. 6 // Copyright (c) 2014年 zfan. All rights reserved. 7 // 8 9 #import "ZFViewController.h" 10 #import "MBProgressHUD+MJ.h" 11 12 @interface ZFViewControll