一. NSURLSesscion概述
1.0 简介
2013 年的 WWDC 大会上,iOS 7.0 推出了 NSURLSession,对 Foundation URL 加载系统进行了彻底的重构,提供了更丰富的 API 来处理网络请求,如:支持 http2.0 协议、直接把数据下载到磁盘、同一 session 发送多个请求、下载是多线程异步处理和提供全局的 session 并可以统一配置等等,提高了 NSURLSession 的易用性、灵活性,更加地适合移动开发的需求。
1.1 NSURLSesscion使用步骤
- 创建NSMutableURLRequest
- 使用NSURLSession对象创建NSURLSessionTask
- 执行Task
1.2 创建NSURLSession
获得共享的Session
+ (NSURLSession *)sharedSession;
自定义Session
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(id )delegate delegateQueue:(NSOperationQueue *)queue;
1.3 创建NSURLSessionTask
常见方法
- (void)suspend; // 暂停
- (void)resume; // 恢复
- (void)cancel; // 取消
@property (readonly, copy) NSError *error; // 错误
@property (readonly, copy) NSURLResponse *response; // 响应
二. NSURLSesscion的使用
1.0 get请求
- (void)getNetwork
{
// 1.0 url
NSURL *url = [NSURL URLWithString:@"https://apitest3.drstrong.cn/health-cure/cure/consult/count/not-handle?doctorId=35573&token=e8dc2e74694df8689089&ucDoctorId=625371"];
// 2.0 创建请求体
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
// 2.1 设置header
[request setValue:@"13979af4eda34f70a305c70a0cb86c7b" forHTTPHeaderField:@"token"];
// 3.0 创建回话
NSURLSession *session = [NSURLSession sharedSession];
// 4.0 创建task
NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 解析数据
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
// 5.0 执行Task
[task resume];
}
1.1 postFrom请求
- (void)postFromNetWork
{
// 1.0 确定请求路径
NSURL *url = [NSURL URLWithString:@"https://apitest3.drstrong.cn/health-doctor/checkVersion"];
// 2.0 创建可变请求对象
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
// 2.1 修改请求方法,POST必须大写
[request setHTTPMethod:@"POST"];
// 2.2 设置属性, 请求超时
request.timeoutInterval = 5;
// 2.3 设置header
[request setValue:@"13979af4eda34f70a305c70a0cb86c7b" forHTTPHeaderField:@"token"];
// 设置请求的格式from类型, 默认可以不设置
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
// 2.4 设置请求体
request.HTTPBody = [@"doctorId=35573&paltform=iphone&token=e8dc2e74694df8689089&version=2.3.1" dataUsingEncoding:NSUTF8StringEncoding];
// 3.0 创建回话对象
NSURLSession *session = [NSURLSession sharedSession];
// 4.0 创建Task
NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//4.解析数据
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
NSLog(@"%zd",res.statusCode);
NSLog(@"%@",[NSThread currentThread]);
}];
// 5.0 执行Task
[task resume];
}
1.2 postJson请求
- (void)useSessionDelegate
{
// 1.0 确定请求路径
NSURL *url = [NSURL URLWithString:@"https://apitest3.drstrong.cn/health-im/im/group/infosNew?token=e8dc2e74694df8689089&doctorId=35573"];
// 2.0 创建可变请求对象
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
// 2.1 修改请求方法,POST必须大写
[request setHTTPMethod:@"POST"];
// 2.2 设置属性, 请求超时
request.timeoutInterval = 5;
// 2.3 设置header
[request setValue:@"990472e1ff8146fca638597f5f0e51d2" forHTTPHeaderField:@"token"];
// 设置请求的格式json类型, 必须要设置
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
// 2.4 设置请求体
NSMutableDictionary *bodyDic = [NSMutableDictionary dictionary];
bodyDic[@"identityType"] = @"1";
bodyDic[@"empty"] = @(NO);
bodyDic[@"doctorId"] = @"35573";
bodyDic[@"token"] = @"e8dc2e74694df8689089";
bodyDic[@"groupIds"] = @"171565222264834,170922752409603";
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:bodyDic options:kNilOptions error:nil];
request.HTTPBody = jsonData;
/*
3.0 创建回话对象
参数1: 配置信息
参数2: 代理
参数3: 代理在那个线程中执行
*/
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
/* NSURLSessionConfiguration: 对象用于初始化NSURLSession对象。当NSURLSession开启多个任务Task的时候可以用NSURLSessionConfiguration对象统一配置。会话在初始化时复制它们的配置,NSURLSession有一个只读的配置属性,设置该配置对这个会话无效。配置是在初始化时被读取一次,之后都是不会变化的。
一. NSURLSessionConfiguration有三个类构造函数
(1). defaultSessionConfiguration: 返回标准默认配置,一般我们都使用这个
(2). ephemeralSessionConfiguration: 返回一个预设配置,没有持久性存储的缓存,Cookie或证书。可以用来实现像"无痕浏览"功能的功能。
(3). backgroundSessionConfiguration:独特之处在于,它会创建一个后台会话。它甚至可以在应用程序挂起,退出,崩溃的情况下运行上传和下载任务。
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
请求超时时间
configuration.timeoutIntervalForRequest = 10;
加载资源超时时间
configuration.timeoutIntervalForResource = 10;
蜂窝网络状态下是否可用
configuration.allowsCellularAccess = YES;
*/
// 4.0 创建Task
NSURLSessionTask *task = [session dataTaskWithRequest:request];
// 5.0 执行Task
[task resume];
}
#pragma mark - <NSURLSessionDataDelegate>
/// 1.0 接收到服务器的响应 它默认会取消该请求
/// @param session 当前回话
/// @param dataTask 请求任务
/// @param response 响应头
/// @param completionHandler 回调, 传给系统
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
NSLog(@"%@", response);
NSLog(@"%s",__func__);
/*
NSURLSessionResponseCancel = 0,取消 默认
NSURLSessionResponseAllow = 1, 接收
NSURLSessionResponseBecomeDownload = 2, 变成下载任务
NSURLSessionResponseBecomeStream 变成流
*/
completionHandler(NSURLSessionResponseAllow);
}
/// 2.0 接收到服务器返回的数据 调用多次
/// @param session 回话对象
/// @param dataTask 请求任务
/// @param data 本次下载的数据
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
NSLog(@"%s",__func__);
//解析数据, 多次调用
NSLog(@"----%@----",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
NSDictionary *param = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(@"%@", param);
}
/// 3.0 请求结束或者失败时候调用
/// @param session 回话对象
/// @param task 请求任务
/// @param error 错误信息
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(nullable NSError *)error
{
NSLog(@"%s",__func__);
}
1.3 下载请求(Block)
//优点:不需要担心内存
//缺点:无法监听文件下载进度
-(void)download
{
//1.url
NSURL *url = [NSURL URLWithString:@"https://file.drstrong.cn/user/6746656/feedback/006b057e47b34811bc07cff310a398ac"];
//2.创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.创建session
NSURLSession *session = [NSURLSession sharedSession];
//4.创建Task
/*
第一个参数:请求对象
第二个参数:completionHandler 回调
location:
response:响应头信息
error:错误信息
*/
//该方法内部已经实现了边接受数据边写沙盒(tmp)的操作
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//6.处理数据
NSLog(@"%@---%@",location,[NSThread currentThread]);
//6.1 拼接文件全路径
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
//6.2 剪切文件
[[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
NSLog(@"%@",fullPath);
}];
//5.执行Task
[downloadTask resume];
}
1.4 下载请求(Delegate)
-(void)delegate
{
//1.url
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_03.png"];
//2.创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.创建session
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//4.创建Task
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];
//5.执行Task
[downloadTask resume];
}
#pragma mark ----------------------
#pragma mark NSURLSessionDownloadDelegate
/**
* 写数据
*
* @param session 会话对象
* @param downloadTask 下载任务
* @param bytesWritten 本次写入的数据大小
* @param totalBytesWritten 下载的数据总大小
* @param totalBytesExpectedToWrite 文件的总大小
*/
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
//1. 获得文件的下载进度
NSLog(@"%f",1.0 * totalBytesWritten/totalBytesExpectedToWrite);
}
/**
* 当恢复下载的时候调用该方法
*
* @param fileOffset 从什么地方下载
* @param expectedTotalBytes 文件的总大小
*/
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
NSLog(@"%s",__func__);
}
/**
* 当下载完成的时候调用
*
* @param location 文件的临时存储路径
*/
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSLog(@"%@",location);
//1 拼接文件全路径
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
//2 剪切文件
[[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
NSLog(@"%@",fullPath);
}
/**
* 请求结束
*/
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(@"didCompleteWithError");
}
1.5 下载请求(断点下载)
- (IBAction)startBtnClick:(id)sender
{
//1.url
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
//2.创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.创建session
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
self.session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//4.创建Task
NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request];
//5.执行Task
[downloadTask resume];
self.downloadTask = downloadTask;
}
//暂停是可以恢复
- (IBAction)suspendBtnClick:(id)sender
{
NSLog(@"+++++++++++++++++++暂停");
[self.downloadTask suspend];
}
//cancel:取消是不能恢复
//cancelByProducingResumeData:是可以恢复
- (IBAction)cancelBtnClick:(id)sender
{
NSLog(@"+++++++++++++++++++取消");
//[self.downloadTask cancel];
//恢复下载的数据!=文件数据
[self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
self.resumData = resumeData;
}];
}
- (IBAction)goOnBtnClick:(id)sender
{
NSLog(@"+++++++++++++++++++恢复下载");
if(self.resumData)
{
self.downloadTask = [self.session downloadTaskWithResumeData:self.resumData];
}
[self.downloadTask resume];
}
代理同上
...
1.5 下载请求(断点续传下载)
- 同NSURLConnention一个揍性, 不能用downloadTask方法
@implementation ViewController
-(void)viewDidLoad
{
[super viewDidLoad];
//1.读取保存的文件总大小的数据,0
//2.获得当前已经下载的数据的大小
//3.计算得到进度信息
}
-(NSString *)fullPath
{
if (_fullPath == nil) {
//获得文件全路径
_fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:FileName];
}
return _fullPath;
}
-(NSURLSession *)session
{
if (_session == nil) {
//3.创建会话对象,设置代理
/*
第一个参数:配置信息 [NSURLSessionConfiguration defaultSessionConfiguration]
第二个参数:代理
第三个参数:设置代理方法在哪个线程中调用
*/
_session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;
}
-(NSURLSessionDataTask *)dataTask
{
if (_dataTask == nil) {
//1.url
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
//2.创建请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//3 设置请求头信息,告诉服务器请求那一部分数据
self.currentSize = [self getFileSize];
NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentSize];
[request setValue:range forHTTPHeaderField:@"Range"];
//4.创建Task
_dataTask = [self.session dataTaskWithRequest:request];
}
return _dataTask;
}
-(NSInteger)getFileSize
{
//获得指定文件路径对应文件的数据大小
NSDictionary *fileInfoDict = [[NSFileManager defaultManager]attributesOfItemAtPath:self.fullPath error:nil];
NSLog(@"%@",fileInfoDict);
NSInteger currentSize = [fileInfoDict[@"NSFileSize"] integerValue];
return currentSize;
}
- (IBAction)startBtnClick:(id)sender
{
[self.dataTask resume];
}
- (IBAction)suspendBtnClick:(id)sender
{
NSLog(@"_________________________suspend");
[self.dataTask suspend];
}
//注意:dataTask的取消是不可以恢复的
- (IBAction)cancelBtnClick:(id)sender
{
NSLog(@"_________________________cancel");
[self.dataTask cancel];
self.dataTask = nil;
}
- (IBAction)goOnBtnClick:(id)sender
{
NSLog(@"_________________________resume");
[self.dataTask resume];
}
#pragma mark ----------------------
#pragma mark NSURLSessionDataDelegate
/**
* 1.接收到服务器的响应 它默认会取消该请求
*
* @param session 会话对象
* @param dataTask 请求任务
* @param response 响应头信息
* @param completionHandler 回调 传给系统
*/
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
//获得文件的总大小
//expectedContentLength 本次请求的数据大小
self.totalSize = response.expectedContentLength + self.currentSize;
if (self.currentSize == 0) {
//创建空的文件
[[NSFileManager defaultManager]createFileAtPath:self.fullPath contents:nil attributes:nil];
}
//创建文件句柄
self.handle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];
//移动指针
[self.handle seekToEndOfFile];
/*
NSURLSessionResponseCancel = 0,取消 默认
NSURLSessionResponseAllow = 1, 接收
NSURLSessionResponseBecomeDownload = 2, 变成下载任务
NSURLSessionResponseBecomeStream 变成流
*/
completionHandler(NSURLSessionResponseAllow);
}
/**
* 接收到服务器返回的数据 调用多次
*
* @param session 会话对象
* @param dataTask 请求任务
* @param data 本次下载的数据
*/
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
// [self.handle seekToEndOfFile]; 不用写, writeData会自动移动到末尾
// 写入数据到文件
[self.handle writeData:data];
// 计算文件的下载进度
self.currentSize += data.length;
NSLog(@"%f",1.0 * self.currentSize / self.totalSize);
self.proessView.progress = 1.0 * self.currentSize / self.totalSize;
}
/**
* 请求结束或者是失败的时候调用
*
* @param session 会话对象
* @param dataTask 请求任务
* @param error 错误信息
*/
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(@"%@",self.fullPath);
//关闭文件句柄
[self.handle closeFile];
self.handle = nil;
}
-(void)dealloc
{
//清理工作
//finishTasksAndInvalidate
[self.session invalidateAndCancel];
}
@end
1.6 实现文件上传
@implementation ViewController
-(NSURLSession *)session
{
if (_session == nil) {
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
//是否运行蜂窝访问
config.allowsCellularAccess = YES;
config.timeoutIntervalForRequest = 15;
_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self upload];
}
-(void)upload
{
//1.url
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];
//2.创建请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//2.1 设置请求方法
request.HTTPMethod = @"POST";
//2.2 设请求头信息
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary] forHTTPHeaderField:@"Content-Type"];
//3.创建会话对象
// NSURLSession *session = [NSURLSession sharedSession];
//4.创建上传TASK
/*
第一个参数:请求对象
第二个参数:传递是要上传的数据(请求体)
第三个参数:
*/
NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromData:[self getBodyData] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//6.解析
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
//5.执行Task
[uploadTask resume];
}
-(NSData *)getBodyData
{
NSMutableData *fileData = [NSMutableData data];
//5.1 文件参数
/*
--分隔符
Content-Disposition: form-data; name="file"; filename="Snip20160225_341.png"
Content-Type: image/png(MIMEType:大类型/小类型)
空行
文件参数
*/
[fileData appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
[fileData appendData:KNewLine];
//name:file 服务器规定的参数
//filename:Snip20160225_341.png 文件保存到服务器上面的名称
//Content-Type:文件的类型
[fileData appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"Sss.png\"" dataUsingEncoding:NSUTF8StringEncoding]];
[fileData appendData:KNewLine];
[fileData appendData:[@"Content-Type: image/png" dataUsingEncoding:NSUTF8StringEncoding]];
[fileData appendData:KNewLine];
[fileData appendData:KNewLine];
UIImage *image = [UIImage imageNamed:@"Snip20160226_90"];
//UIImage --->NSData
NSData *imageData = UIImagePNGRepresentation(image);
[fileData appendData:imageData];
[fileData appendData:KNewLine];
//5.2 非文件参数
/*
--分隔符
Content-Disposition: form-data; name="username"
空行
123456
*/
[fileData appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
[fileData appendData:KNewLine];
[fileData appendData:[@"Content-Disposition: form-data; name=\"username\"" dataUsingEncoding:NSUTF8StringEncoding]];
[fileData appendData:KNewLine];
[fileData appendData:KNewLine];
[fileData appendData:[@"123456" dataUsingEncoding:NSUTF8StringEncoding]];
[fileData appendData:KNewLine];
//5.3 结尾标识
/*
--分隔符--
*/
[fileData appendData:[[NSString stringWithFormat:@"--%@--",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
return fileData;
}
#pragma mark ----------------------
#pragma mark NSURLSessionDataDelegate
/*
* @param bytesSent 本次发送的数据
* @param totalBytesSent 上传完成的数据大小
* @param totalBytesExpectedToSend 文件的总大小
*/
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
NSLog(@"%f",1.0 *totalBytesSent / totalBytesExpectedToSend);
}
@end
二. NSURLSessionConfiguration
1.0 概述
-
NSURLSessionConfiguration对象用于初始化NSURLSession对象。
-
展开请求级别中与NSMutableURLRequest相关的可供选择的方案,我们可以看到NSURLSessionConfiguration对于会话如何产生请求,提供了相当多的控制和灵活性。从网络访问性能,到cookie,安全性,缓存策略,自定义协议,启动事件设置,以及用于移动设备优化的几个新属性,你会发现你一直在寻找的,正是NSURLSessionConfiguration。
-
会话在初始化时复制它们的配置,NSURLSession有一个只读的配置属性,使得该配置对象上的变化对这个会话的政策无效。配置在初始化时被读取一次,之后都是不会变化的。
1.1 构造方法
- NSURLSessionConfiguration有三个类构造函数,这很好地说明了NSURLSession是为不同的用例而设计的。
+ "defaultSessionConfiguration"返回标准配置,这实际上与NSURLConnection的网络协议栈是一样的,具有相同的共享NSHTTPCookieStorage,共享NSURLCache和共享NSURLCredentialStorage。
+ "ephemeralSessionConfiguration"返回一个预设配置,没有持久性存储的缓存,Cookie或证书。这对于实现像"秘密浏览"功能的功能来说,是很理想的。
+ "backgroundSessionConfiguration":独特之处在于,它会创建一个后台会话。后台会话不同于常规的,普通的会话,它甚至可以在应用程序挂起,退出,崩溃的情况下运行上传和下载任务。初始化时指定的标识符,被用于向任何可能在进程外恢复后台传输的守护进程提供上下文。
- 想要查看更多关于后台会话的信息,可以查看WWDC Session 204: “What’s New with Multitasking”
1.2 Configuration属性
NSURLSessionConfiguration拥有20个属性。熟练掌握这些属性的用处,将使应用程序充分利用其网络环境。
- 最重要的属性:
1. 替代 request 中的 forHTTPHeaderField 告诉服务器有关客户端的附加信息
"HTTPAdditionalHeaders"指定了一组默认的可以设置出站请求的数据头。这对于跨会话共享信息,如内容类型,语言,用户代理,身份认证,是很有用的。
2. WebDav的身份验证
NSString *userPasswordString = [NSString stringWithFormat:@"%@:%@", user, password];
NSData * userPasswordData = [userPasswordString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64EncodedCredential = [userPasswordData base64EncodedStringWithOptions:0];
NSString *authString = [NSString stringWithFormat:@"Basic: %@", base64EncodedCredential];
3. 设置客户端类型
NSString *userAgentString = @"iPhone AppleWebKit";
configuration.HTTPAdditionalHeaders = @{@"Accept": @"application/json",
@"Accept-Language": @"en",
@"Authorization": authString,
@"User-Agent": userAgentString};
4. "networkServiceType(网络服务类型)"对标准的网络流量,网络电话,语音,视频,以及由一个后台进程使用的流量进行了区分。大多数应用程序都不需要设置这个
5. "allowsCellularAccess(允许蜂窝访问)"和"discretionary(自行决定)"被用于节省通过蜂窝连接的带宽。建议在使用后台传输的时候,使用discretionary属性,而不是allowsCellularAccess属性,因为它会把WiFi和电源可用性考虑在内
6. "timeoutIntervalForRequest"和"timeoutIntervalForResource"指定了请求以及该资源的超时时间间隔。许多开发人员试图使用timeoutInterval去限制发送请求的总时间,但这误会了timeoutInterval的意思:报文之间的时间。timeoutIntervalForResource实际上提供了整体超时的特性,这应该只用于后台传输,而不是用户实际上可能想要等待的任何东西
7. "HTTPMaximumConnectionsPerHost"是 Foundation 框架中URL加载系统的一个新的配置选项。它曾经被用于NSURLConnection管理私人连接池。现在有了NSURLSession,开发者可以在需要时限制连接到特定主机的数量
8. "HTTPShouldUsePipelining"也出现在NSMutableURLRequest,它可以被用于开启HTTP管道,这可以显着降低请求的加载时间,但是由于没有被服务器广泛支持,默认是禁用的
9. "sessionSendsLaunchEvents" 是另一个新的属性,该属性指定该会话是否应该从后台启动
10. "connectionProxyDictionary"指定了会话连接中的代理服务器。同样地,大多数面向消费者的应用程序都不需要代理,所以基本上不需要配置这个属性
关于连接代理的更多信息可以在 CFProxySupport Reference 找到。
- "Cookie Policies"
-"HTTPCookieStorage" 是被会话使用的cookie存储。默认情况下,NSHTTPCookieShorage的 + sharedHTTPCookieStorage会被使用,这与NSURLConnection是相同的
-"HTTPCookieAcceptPolicy" 决定了该会话应该接受从服务器发出的cookie的条件
-"HTTPShouldSetCookies" 指定了请求是否应该使用会话HTTPCookieStorage的cookie
- "Security Policies"
URLCredentialStorage 是会话使用的证书存储。默认情况下,NSURLCredentialStorage 的+ sharedCredentialStorage 会被使用使用,这与NSURLConnection是相同的
"TLSMaximumSupportedProtocol" 和 "TLSMinimumSupportedProtocol" 确定是否支持SSLProtocol版本的会话
- "Caching Policies"
URLCache 是会话使用的缓存。默认情况下,NSURLCache 的 + sharedURLCache 会被使用,这与NSURLConnection是相同的
requestCachePolicy 指定了一个请求的缓存响应应该在什么时候返回。这相当于NSURLRequest 的-cachePolicy方法
- "Custom Protocols"
protocolClasses是注册NSURLProtocol类的特定会话数组