有的程序员老了,还没听过NSURLSession
有的程序员还嫩,没用过NSURLConnection
有的程序员很单纯,他只知道AFN.
NSURLConnection在iOS9被宣布弃用,NSURLSession从13年发展到现在,终于迎来了它独步江湖的时代.NSURLSession是苹果在iOS7后为HTTP数据传输提供的一系列接口,比NSURLConnection强大,坑少,好用.今天从使用的角度介绍下.
除了NSURLSession
,文中还会频繁地出现NSURLSessionConfiguration
和NSURLSessionTask
两个类.先认识一下,混个脸熟吧.
使用NSURLSession,拢共分两步:
- 第一步 通过NSURLSession的实例创建task
- 第二部 执行task
既然两步里面都出现了task,就先说说它吧.
NSURLSessionTask可以简单理解为任务:如数据请求任务,下载任务,上传任务and so on.我们使用的是他的子类们:
- NSURLSessionTask(抽象类)
- NSURLSessionDataTask
- NSURLSessionUploadTask
- NSURLSessionDownloadTask
- NSURLSessionDataTask
从这几个子类的名字就可以大概猜出他们的作用了.接下来我们就从不同类型的任务出发,来使用session.
NSURLSessionDataTask
字面上看是和数据相关的任务,但其实dataTask完全可以胜任downloadTask和uploadTask的工作.这可能也是我们使用最多的task种类.
简单GET请求
如果请求的数据比较简单,也不需要对返回的数据做一些复杂的操作.那么我们可以使用带block
// 快捷方式获得session对象
NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:@"http://www.daka.com/login?username=daka&pwd=123"];
// 通过URL初始化task,在block内部可以直接对返回的数据进行处理
NSURLSessionTask *task = [session dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response, NSError error) {
NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
}]; // 启动任务
[task resume];
Tips:
- 所有类型的task都要调用resume方法才会开始进行请求.
简单POST请求
POST和GET的区别就在于request,所以使用session的POST请求和GET过程是一样的,区别就在于对request的处理.
NSURL *url = [NSURL URLWithString:@"http://www.daka.com/login"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
request.HTTPBody = [@"username=daka&pwd=123" dataUsingEncoding:NSUTF8StringEncoding]; NSURLSession *session = [NSURLSession sharedSession];
// 由于要先对request先行处理,我们通过request初始化task
NSURLSessionTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]); }];
[task resume];
NSURLSessionDataDelegate代理方法
NSURLSession提供了block方式处理返回数据的简便方式,但如果想要在接收数据过程中做进一步的处理,仍然可以调用相关的协议方法.NSURLSession的代理方法和NSURLConnection有些类似,都是分为接收响应、接收数据、请求完成几个阶段.
// 使用代理方法需要设置代理,但是session的delegate属性是只读的,要想设置代理只能通过这种方式创建session
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
delegate:self
delegateQueue:[[NSOperationQueue alloc] init]]; // 创建任务(因为要使用代理方法,就不需要block方式的初始化了)
NSURLSessionDataTask *task = [session dataTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.daka.com/login?userName=daka&pwd=123"]]]; // 启动任务
[task resume]; //对应的代理方法如下: // 1.接收到服务器的响应
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
// 允许处理服务器的响应,才会继续接收服务器返回的数据
completionHandler(NSURLSessionResponseAllow);
} // 2.接收到服务器的数据(可能调用多次)
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
// 处理每次接收的数据
} // 3.请求成功或者失败(如果失败,error有值)
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
// 请求完成,成功或者失败的处理
}
Tips:
关键点在代码注释里面都有提及,重要的地方再强调一下:
- 如果要使用代理方法,需要设置代理,但从NSURLSession的头文件发现session的delegate属性是只读的.因此设置代理要通过session的初始化方法赋值:
sessionWithConfiguration:delegate:delegateQueue:
其中:- configuration参数(文章开始提到的)需要传递一个配置,我们暂且使用默认的配置
[NSURLSessionConfiguration defaultSessionConfiguration]
就好(后面会说下这个配置是干嘛用的); - delegateQueue参数表示协议方法将会在哪个队列(NSOperationQueue)里面执行.
- configuration参数(文章开始提到的)需要传递一个配置,我们暂且使用默认的配置
- NSURLSession在接收到响应的时候要先对响应做允许处理:
completionHandler(NSURLSessionResponseAllow);
,才会继续接收服务器返回的数据,进入后面的代理方法.值得一提的是,如果在接收响应的时候需要对返回的参数进行处理(如获取响应头信息等),那么这些处理应该放在前面允许操作的前面.
NSURLSessionDownloadTask
文件下载可以使用NSURLSessionDownloadTask这个子类.
简单下载
NSURLSessionDownloadTask同样提供了通过NSURL和NSURLRequest两种方式来初始化并通过block进行回调的方法.下面以NSURL初始化为例:
NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:@"http://www.daka.com/resources/image/icon.png"] ;
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
// location是沙盒中tmp文件夹下的一个临时url,文件下载后会存到这个位置,由于tmp中的文件随时可能被删除,所以我们需要自己需要把下载的文件挪到需要的地方
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
// 剪切文件
[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:path] error:nil];
}];
// 启动任务
[task resume];
Tips:
- 需要注意的就是需要将下载到tmp文件夹的文件转移到需要的目录.原因在代码中已经贴出.
-
response.suggestedFilename
是从相应中取出文件在服务器上存储路径的最后部分,如数据在服务器的url为http://www.daka.com/resources/image/icon.png
, 那么其suggestedFilename就是icon.png.
NSURLSessionDownloadDelegate代理方法
同样的,downloadTask也提供了配套的代理方法
// 每次写入调用(会调用多次)
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
// 可在这里通过已写入的长度和总长度算出下载进度
CGFloat progress = 1.0 * totalBytesWritten / totalBytesExpectedToWrite; NSLog(@"%f",progress);
} // 下载完成调用
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location {
// location还是一个临时路径,需要自己挪到需要的路径(caches下面)
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePath] error:nil];
} // 任务完成调用
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { }
NSURLSessionUploadTask
在NSURLSession中,文件上传方式主要有以下两种:
NSURLSessionUploadTask *task =[[NSURLSession sharedSession] uploadTaskWithRequest:request
fromFile:fileName
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {}];
和
[self.session uploadTaskWithRequest:request
fromData:body
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"-------%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
}];
处于安全性考虑,通常我们会使用POST方式进行文件上传,所以较多使用第二种方式.
但是,NSURLSession并没有为我们提供比NSURLConnection更方便的文件上传方式.方法中body
处的参数需要填写request的请求体(http协议规定格式的大长串).因为你有90%的可能性用了AFNetworking,即使是自己写的应该也是copy,所以代码就不贴了我们只说方法呵呵哒.
断点下载
NSURLSessionDownloadTask提供了与断点下载相关的几个方法:
// 使用这种方式取消下载可以得到将来用来恢复的数据,保存起来
[self.task cancelByProducingResumeData:^(NSData *resumeData) {
self.resumeData = resumeData;
}]; // 由于下载失败导致的下载中断会进入此协议方法,也可以得到用来恢复的数据
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
// 保存恢复数据
self.resumeData = error.userInfo[NSURLSessionDownloadTaskResumeData];
} // 恢复下载时接过保存的恢复数据
self.task = [self.session downloadTaskWithResumeData:self.resumeData];
// 启动任务
[self.task resume];
以目前我对NSURLSession的理解这种断点下载只支持应用内断点,如果程序在下载过程中途关闭,则不能恢复下载.(暂时对NSURLSession理解还不全面,不敢妄下断论,如有不妥简友们可以沟通下)
其他
此外,task们自身有都拥有下面几个方法
- (void)suspend;
- (void)resume;
- (void)cancel;
suspend可以让当前的任务暂停
resume方法不仅可以启动任务,还可以唤醒suspend状态的任务
cancel方法可以取消当前的任务,你也可以向处于suspend状态的任务发送cancel消息,任务如果被取消便不能再恢复到之前的状态.
NSURLSessionConfiguration
简单地说,就是session的配置信息.如:
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
// 超时时间
config.timeoutIntervalForRequest = ;
// 是否允许使用蜂窝网络(后台传输不适用)
config.allowsCellularAccess = YES;
// 还有很多可以设置的属性
有没有发现我们使用的Configuration都是默认配置:[NSURLSessionConfiguration defaultSessionConfiguration]
,其实它的配置有三种类型:
+ (NSURLSessionConfiguration *)defaultSessionConfiguration;
+ (NSURLSessionConfiguration *)ephemeralSessionConfiguration;
+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier
表示了NSURLSession几种不同的工作模式.
默认的配置会将缓存存储在磁盘上,第二种瞬时会话模式不会创建持久性存储的缓存,第三种后台会话模式允许程序在后台进行上传下载工作.
除了支持任务的暂停和断点续传,我觉得NSURLSession之于NSURLConnection的最伟大的进步就是支持后台上传下载任务,这又是一个可以深入讨论的话题.但在这方面我还没有进行深入的研究,待后续了解之后另行开贴.
PS:AFNetWorking从2.0版本就有了基于NSURLSession的系列封装,感兴趣的童鞋自行前往了解.
原文链接:http://www.jianshu.com/p/fafc67475c73
[OC] NSURLSession的更多相关文章
-
OC - 15.NSURLSession与NSURLSessionTask
简介 NSURLSession也能完成网络请求 NSURLConnection在iOS9中不推荐使用,NSURLSession是iOS9中推荐使用的网络请求方式 NSURLSession需要与NSUR ...
-
iOS开发——网络篇——NSURLSession,下载、上传代理方法,利用NSURLSession断点下载,AFN基本使用,网络检测,NSURLConnection补充
一.NSURLConnection补充 前面提到的NSURLConnection有些知识点需要补充 NSURLConnectionDataDelegate的代理方法有一下几个 - (void)conn ...
-
NSURLConnection、NSURLSession
NSURLConnection 1.准备网络资源地址:URL 注意:由于URL支持26个英文字母,数字和少数的几个特殊字符. 因此对于URL中包含非标准URL的字符,需要进行编码. iOS提供了函 ...
-
(一二七)NSURLSession的基本用法 下载与数据获取
简介 NSURLSession是苹果官方提供的一系列网络接口库,使用他们可以轻松实现下载和数据获取等任务.在上一篇文章中,我们介绍了使用NSURLConnection下载文件和断点续传的功能,实现起来 ...
-
24、JSON与OC互相转化
一. JSON: 1. 01.JSON是一种轻量级的数据格式,一般用于数据交互 02.服务器返回给客户端的数据,一般都是JSON格式活着XML格式(文件下载除外) JSON的格式很像OC中的字典和数组 ...
-
swift3.0:NSURLSession的使用
一.说明 NSURLSession是OC中的会话类,在Swift中变成URLSession类,它们的实现方式是一样的,下面的示例就Swift语法进行讲解和介绍. 二.介绍: URLSession 类支 ...
-
百度智能(文本识别),API传图OC代码与SDK使用
百度智能中的文本识别中的身份证识别,有API方式和SDK方式 API方式 百度智能(文本识别),百度API传图没有提供OC的示例,这里提供一下 - (void)OCTest:(NSString*)to ...
-
iOS代码规范(OC和Swift)
下面说下iOS的代码规范问题,如果大家觉得还不错,可以直接用到项目中,有不同意见 可以在下面讨论下. 相信很多人工作中最烦的就是代码不规范,命名不规范,曾经见过一个VC里有3个按钮被命名为button ...
-
用C语言封装OC对象(耐心阅读,非常重要)
用C语言封装OC对象(耐心阅读,非常重要) 本文的主要内容来自这里 前言 做iOS开发的朋友,对OC肯定非常了解,那么大家有没有想过OC中NSInteger,NSObject,NSString这些对象 ...
随机推荐
-
CentOS Yum 命令详解
总所周知,Redhat和Fedora的软件安装命令是rpm,但是用rpm安 装软件最大的麻烦就是需要手动寻找安装该软件所需要的一系列依赖关系,超级麻烦不说,要是软件不用了需要卸载的话由于卸载掉了某个依 ...
-
[Asp.net Mvc]通过UrlHelper扩展为js,css静态文件添加版本号
写在前面 在app中嵌入h5应用,最头疼的就是缓存的问题,比如你修改了一个样式,或者在js中添加了一个方法,发布之后,并没有更新,加载的仍是缓存里面的内容.这个时候就需要清理缓存才能解决.但又不想让w ...
-
hadoop2.2.0的WordCount程序
package com.my.hadoop.mapreduce.wordcount; import java.io.IOException; import org.apache.hadoop.conf ...
-
Akka(11): 分布式运算:集群-均衡负载
在上篇讨论里我们主要介绍了Akka-Cluster的基本原理.同时我们也确认了几个使用Akka-Cluster的重点:首先,Akka-Cluster集群构建与Actor编程没有直接的关联.集群构建是A ...
-
终于开始我的java旅程了!
首先今天先装了jdk1.7 ,找了半天,因为官网是都是让你装1.8的最新版本,地址如下: 所有jdk的历史版本: http://www.oracle.com/technetwork/java/java ...
-
Elasticsearch--Aggregation详细总结(聚合统计)
Elasticsearch的Aggregation功能也异常强悍. Aggregation共分为三种:Metric Aggregations.Bucket Aggregations. Pipeline ...
-
【Java】 剑指offer(44) 连续子数组的最大和
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 数字以0123456789101112131415…的格式序列化到 ...
-
FluentScheduler:开源轻量级定时任务调度架构
安装:FluentScheduler Install-Package FluentScheduler 一.控制台中使用 using System; using System.Collections.G ...
-
win10常用命令和设置总结
1.常用命令 exit:退出cmd面板; cls:清除cmd面板; 2.常用设置 2.1 services.msc 禁用:以后怎样都不会运行;手动:是打开某些用到它的程序要用到该服务时才会运行; 自动 ...
-
golang init函数
init函数有一下几点特性: init函数在main执行之前,自动被调用执行的,不能显示调用 每个包的init函数在包被引用时,自动被调用 每个包可以有多个init函数 同一个文件中可定义多个init ...