NSURLSession 在ios7的时候,推出这个。主要是用来替换NSURLConnection。
NSURLSession是一组相互依赖的类,它的大部分组件和NSURLConnection中的组件相同如NSURLRequest,NSURLCache等。而NSURLSession的不同之处在于,它将NSURLConnection替换为NSURLSession和NSURLSessionConfiguration,以及3个NSURLSessionTask的子类:NSURLSessionDataTask, NSURLSessionUploadTask, 和NSURLSessionDownloadTask。
关于图例:
NSURLSession由NSURLSessionConfiguration和可选代理(optional delegate)构成。再根据你的网络需求通过NSURLSessionTask来创建session。
1、NSURLSessionConfiguration
简介
- NSURLSessionConfiguration主要用于配置NSURLSession会话属性,其工作模式主要有三种:
- 默认模式(defaultSessionConfiguration):使用硬盘来缓存数据,可以使用缓存的Cache,Cookie,鉴权。
- 及时模式(ephemeralSessionConfiguration): 临时session配置,与默认配置相比,这个配置不会将缓存、cookie等存在本地,只会存在内存里,所以当程序退出时,所有的数据都会消失
- 后台模式(backgroundSessionConfiguration):在后台完成上传下载,创建Configuration对象的时候需要给一个NSString的ID用于追踪完成工作的Session是哪一个。 做远程push通知或是应用程序挂起的时候就要用到这个configuration。
常用属性
- identifie:设置后台任务的标识符
- requestCachePolicy:设置缓存策略
- timeoutIntervalForRequest:设置请求超时时长
- networkServiceType:设置网络服务类型
- HTTPAdditionalHeaders:设置头部参数
- allowsCellularAccess:设置是否在非无线的情况下请求网络(使用蜂窝数据)
- HTTPMaximumConnectionsPerHost:设置主机网络连接个数
- discretionary: discretionary属性为YES时表示当程序在后台运作时由系统自己选择最佳的网络连接配置,该属性可以节省通过蜂窝连接的带宽。在使用后台传输数据的时候,建议使用
discretionary
属性,而不是allowsCellularAccess
属性,因为它会把WiFi和电源可用性考虑在内。这个标志允许系统为分配任务进行性能优化。这意味着只有当设备有足够电量时,设备才通过Wifi进行数据传输。如果电量低,或者只仅有一个蜂窝连接,传输任务是不会运行的。后台传输总是在discretionary模式下运行。
常用方法
- setHTTPAdditionalHeaders:设置头部/参数
// 设置所有的请求只接收JSON数据;
// 设置网络请求api所需的头部参数;
@"Accept": @"application/json", @"apikey": @"159d95a8c050074fe3ca0df0d901fc62"}];
2、NSURLSession 网络会话
- NSURLSession是为了代替NSURLConnection而设计的。Sessions的所有工作都是通过NSURLSessionTask对象完成。可以用block,delegate,或者两者混合来创建task。
初始化方法:
创建一个NSURLSession,系统提供了三个创建方法:
- sharedSession:使用静态的sharedSession方法,该类使用共享的会话,该会话使用全局的Cache,Cookie和证书。
- sessionWithConfiguration:粒度较低,就是根据NSURLSessionConfiguration对象创建一个Session,系统默认创建一个新的OperationQueue处理Session的消息。
- sessionWithConfiguration:delegate:delegateQueue:粒度较高,可以设定回调的delegate(注意这个回调delegate会被强引用),并且可以设定delegate在哪个OperationQueue回调,如果我们将其设置为
[NSOperationQueue mainQueue]
就能在主线程进行回调,非常的方便。
注意:二三两种方式可以创建一个新会话并定制其会话类型。该方式中指定了session的委托和委托所处的队列。当不再需要连接时,可以调用Session的invalidateAndCancel
直接关闭,或者调用finishTasksAndInvalidate
等待当前Task结束后关闭。这时Delegate会收到URLSession:didBecomeInvalidWithError:
这个事件。Delegate收到这个事件之后会被解引用。
3、NSURLSessionTask 会话任务
- NSURLSessionTask是一个抽象子类,它有三个子类:NSURLSessionDataTask,NSURLSessionUploadTask和NSURLSessionDownloadTask。这三个类封装了现代应用程序的三个基本网络任务:获取数据(比如JSON或XML),以及上传和下载。其集成关系如下图:
a、NSURLSessionDataTask
- 这个task调用HTTP GET请求从服务器获取数据。返回的数据格式是NSData。可能需要你自己转换成XML、JSON等数据格式。
创建方法:
- 通过request对象或url创建:
通过request
(NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;
通过rul
(NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url;
- 通过request对象或url创建,同时指定任务完成后通过completionHandler指定回调的代码块:
通过request创建
(NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error))completionHandler;
通过url创建
(NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error))completionHandler;
b、NSURLSessionUploadTask
这个类是用来上传用的,者上传过程中,能看到上传的状态。
创建方法:
- 通过request创建,在上传时指定文件源或数据源。
通过指定文件源上传
(NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL;
通过指定数据源上传
(NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData;
通过request上传
(NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request;
- 在创建upload task对象时,通过completionHandler指定任务完成后的回调代码块:
(NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;
(NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;
c、NSURLSessionDownloadTask
- NSURLSessionDownloadTask下载文件可以在下载中挂起,恢复。
创建方法:
// 方法1
(NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request;
// 方法2
(NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url;
// 方法3
(NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;
- 下载任务支持断点续传,第三种方式是通过之前已经下载的数据来创建下载任务。
- 同样的可以通过
completionHandler
指定任务完成后的回调代码块:
// 方法1
NSURLRequest *)request completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;
// 方法2
NSURL *)url completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;
// 方法3
void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;
提示:
1、task的类型直接写到一个临时文件中。
2、下载过程中会调用URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite: 去更新状态。
3、当task完成,URLSession:downloadTask:didFinishDownloadingToURL:会被调用。此时你可以将临时文件保存到永久文件中。
4、下载失败或是取消还可以得到已经下载的那一部分数据。
NSURLSessionTask 任务挂起
[task resume];
提示:
同时管理多个task时,可以用taskIdentifier属性来唯一标识task。
- (void)getRequest
{
// 1、构造URL资源地址
NSURL *url = [NSURL URLWithString:Get_Url_String];
// 2、创建Request请求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 3、配置Request请求
// 设置请求方法
request.HTTPMethod = @"GET";
// 设置请求超时
request.timeoutInterval = 10;
// 设置头部
[request addValue:Get_Url_Apikey forHTTPHeaderField:@"apikey"];
//4、构造NSURLSessionConfiguration
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
// 5、构造NSURLSession网络会话
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
// 6、构造NSURLSessionTask会话任务
NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error)
{// 请求失败
NSLog(@"error=%@", error.localizedDescription);
}
else
{// 请求成功,解析数据
// 直接将data数据转换成字符串
NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// JSON数据格式
id object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];
if (error)
{// 解析失败
NSLog(@"解析失败:%@", error.localizedDescription);
}
else
{// 解析成功
NSLog(@"json=%@", object);
}
}
}];
// 喜执行任务
[task resume];
}
- (void)postRequest
{
// 1、创建URL资源地址
NSURL *url = [NSURL URLWithString:Post_Url_String];
// 2、创建Reuest请求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 3、配置Request
request.timeoutInterval = 10.0;
request.HTTPMethod = @"POST";
// 4、构造请求参数
// 4.1、创建字典参数,将参数放入字典中,可防止程序员在主观意识上犯错误,即参数写错。
NSDictionary *parametersDict = @{@"id":Post_Url_Parameter_Id, @"key":Post_Url_Apikey, @"dtype":Post_Url_Parameter_Dtype};
// 4.2、遍历字典,以“key=value&”的方式创建参数字符串。
NSMutableString *parameterString = [NSMutableString string];
for (NSString *key in parametersDict.allKeys)
{
// 拼接字符串
[parameterString appendFormat:@"%@=%@&", key, parametersDict[key]];
}
// 4.3、截取参数字符串,去掉最后一个“&”,并且将其转成NSData数据类型。
NSData *parametersData = [[parameterString substringToIndex:parameterString.length - 1] dataUsingEncoding:NSUTF8StringEncoding];
// 5、设置请求报文
request.HTTPBody = parametersData;
// 6、构造NSURLSessionConfiguration
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
// 7、创建网络会话
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
// 8、创建会话任务
NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 10、判断是否请求成功
if (error) {
NSLOG(error.localizedDescription);
}else {
// 如果请求成功,则解析数据。
id object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];
// 11、判断是否解析成功
if (error) {
NSLOG(error.localizedDescription);
}else {
// 解析成功,处理数据,通过GCD获取主队列,在主线程中刷新界面。
NSLOG(object);
dispatch_async(dispatch_get_main_queue(), ^{
// 刷新界面...
});
}
}
}];
// 9、执行任务
[task resume];
}