什么是NSURLSession、NSURLSessionConfiguration、NSURLSessionTask
NSURLSession:NSURLSession类以及相关类提供了一组用于通过HTTP下载内容的API,这组API中具有许多委托方法用来进行身份验证、后台下载等活动,具有异步性。
NSURLSessionConfiguration:该类定义了使用NSURLSession对象进行上传和下载时的行为和策略,在使用NSURLSession对象时,总是要首先定义该类对象。
NSURLSessionTask:该类是NSURLSession中所有任务的基类,task是session的一部分。任务通过调用NSURLSession对象中的方法进行创建。
注:NSURLSession的行为由session的类型(取决于NSURLSessionConfiguration类型决定)、task类型以及创建task时,App是运行在前台还是后台
Session类型
session类型由configuration对象的类型确定,configuration类型如下:
- defaultSessionConfiguration
- emphemeralSessionConfiguration
- backgroundSessionConfiguration
因此,session的类型也分三种:
- 默认Session:基于磁盘建立缓存,将凭证存储在用户的kaychain中
- 临时Session:所有高速缓存以及凭证都存储在RAM中,不存储任何数据到磁盘,App无法验证session时将删除RAM中的session数据。
- 后台Session:与默认session类似,除了使用一个单独的进程处理所有数据传输外,还有一些其它的限制,具体可参考后台传输的限制小节
Task类型
- 数据任务:使用NSData对象收发数据,主要用于CS之间的临时请求。数据任务可以在每次接收到数据后将数据提交给App,也可以通过处理程序一次将所有数据返回给App。
- 下载任务:以文件的形式检索数据,支持后台下载。
- 上传任务:以文件形式发送数据,支持后台上传。
后台Session的限制
后台Session在进行任务时,实际的数据传输任务由一个单独的进程负责,并且App重启的系统开销较大,所以在使用后台Session时,有如下限制:
- 仅支持HTTP与HTTPs协议(不支持自定义协议)。
- 允许重定向。
- 仅支持文件形式的上传任务(因为从NSData对象和数据流读取数据上传会在程序退出后失败)。
- 在App进入后台时启动了后台传输,则configuration对象的任意属性被视为true。
NSCopy行为
- 在对session对象进行复制时,得到的将是同一个对象。
- 在对configuration对象进行复制时,得到的将是一个可修改的副本。
创建和配置Session
-
创建一个configuration对象管理session的行为。
-
创建一个delegate对象来处理接收数据和指定给session及session内任务的事件。若没有开发者没有提供delegate,那么NSURLSession将使用系统提供的delegate,这样就能使用NSURLSession中的方法代替NSURLConnection的
sendAsynchronousRequest:queue:completionHandler:方法。sessionWithConfiguration://使用系统提供的delegate sessionWithConfiguration:delegate:delegateQueue: //需要自定义delegate,queue不要求为串行队列,但是queue为nil时,系统会自动创建一个串行队列
注:
- 要在后台进行数据传输,必须自定义delegate(重写)
- 除了后台session的configuration对象外,可以重用其他session的configuration对象创建新的session,因为系统没有定义两个后台session共享标识符的行为
- 在创建session时,session对configuration进行了深拷贝,在之后修改configuration并不能对当前的session产生影响,只影响修改后新创建的session
使用系统delegate获取资源
NSURLSession最直接的使用方法就是使用系统提供的delegate请求资源:
- 创建configuration对象和相应的session对象。
- 在数据被完全接收后,使用处理程序对数据进行处理。
注:系统提供的delegate仅支持有限的网络行为的自定义,对于身份验证或后台下载,这种通过简单网址获取资源的方式并不适用
使用自定义delegate获取资源
使用自定义的delegate来获取网络资源,需要至少要实现以下方法:
- URLSession:dataTask:didReceiveData:
该方法每请求一次,任务便得到一份数据。若App要使用该方法返回的数据,需要将数据以某种方式进行存储。 - URLSession:task:didCompleteWithError:
表明任务已完全接收数据
注:dataTaskWithURL:与dataTaskWithURL:completionHandler:两个方法都是获取指定URL网址的内容,但是前者会调用delegate中的URLSession:dataTask:didReceiveData:方法与URLSession:task:didCompleteWithError: 方法,主要用于使用自定义delegate获取资源;后者则会绕过这两种方法,并提供completionHandler来对数据进行处理,但是依然会调用delegate中的用于身份验证的方法,这种则主要用于使用系统delegate获取资源(需要提供completionHandler的方法一般都会绕过自定义delegate要重写的方法,使用系统定义delegate)。
下载文件
文件下载就像是等级更高的获取数据。要实现下载,需要实现以下delegate方法:
- URLSession:downloadTask:didFinishDownloadingToURL:
该方法将根据URL下载的内容存储在临时文件里
重点:此方法返回前,需要对文件进行读取操作或将文件移到一个永久的位置,否则方法在返回时会将在原始位置的临时文件删掉。 - URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
为App提供下载进度的状态信息 - URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:
告诉App能够成功下载之前下载失败的文件 - URLSession:task:didCompleteWithError:
告诉App下载失败。 - 三种下载情况:
- 如果在后台session中安排下载任务,当App停止运行时还能继续进行下载;当在标准session或临时session中进行下载任务,则会在程序重启后,重新下载。
- 用户停止或停止下载时,task调用cancelByProducingResumeData:取消下载,该方法会提供一个resume data用来保存已完成的进度。然后若要在断点处继续进行下载,则将resume data传入到downloadTaskWithResumeData: 或
downloadTaskWithResumeData:completionHandler:就能新建任务继续下载。 - 若数据传输失败(例如任务被取消或者网络中断等),则调用delegate的URLSession:task:didCompleteWithError:方法并附带一个NSError对象,若任务在恢复后可继续进行,则该对象的userInfo字典中包含了键值为NSURLSessionDownloadTaskResumeData的可恢复数据。App就可以通过返回数据到downloadTaskWithResumeData:或
downloadTaskWithResumeData:completionHandler:重试下载。
上传请求体内容
HTTP POST请求的请求体数据来源有三种:NSData对象、文件以及数据流,其使用方式如下:
- 数据存储在内存中,且不会被销毁,则可以使用NSData对象作为请求体内容来源
- 当上传的内容在磁盘的文件上,或者在后台上传文件,又或者App将为了释放内存中的数据而将数据写入磁盘,这些情况下使用文件作为请求体内容来源
- App在通过网络接收数据,这时要使用数据流作为请求体内容来源
session delegate中实现的方法:
- URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
该方法获取上传进度信息 - URLSession:task:needNewBodyStream:
该方法将数据流作为请求体内容来源
使用NSData作为上传请求的请求体内容来源
- uploadTaskWithRequest:fromData:
- uploadTaskWithRequest:fromData:completionHandler:
使用上述方法创建上传任务,将NSData对象通过参数fromData传入,session对象会根据数据对象的大小计算请求头部的Content-Length,App还需要设置请求对象的其他信息,例如:content-type
使用文件作为上传请求的请求体内容来源
- uploadTaskWithRequest:fromFile:
- uploadTaskWithRequest:fromFile:completionHandler:
使用上述方法创建上传任务,fromFile为上传内容所在文件的URL,session对象按照数据对象的大小计算请求头部的Content-Length。如果App没有提供Content-Length值,session对象则会提供了一个。计算请求头部的Content-Length。
使用流作为上传请求的请求体内容来源
- uploadTaskWithStreamedRequest:
该方法创建上传任务,参数request为与数据流关联的NSURLRequest对象。
由于session不能回退重新读取数据流,因此App须要重新提供新的数据流来进行重新请求(例如:认证失败)。URLSession:task:needNewBodyStream:可以解决这一问题,当该方法被调用时,App应当获取或创建一个新的流,之后调用由NSInputStream作参数的block进行处理。
注:这项技术不能用在系统提供的delegate上
使用下载任务来上传文件
使用下载任务来进行上传,必须使用NSData或数据流作为创建请求的NSURLRequest对象的一部分,如果使用数据流进行上传,App须在身份验证失败后调用URLSession:task:needNewBodyStream:重新创建一个新的流,除了返回数据的方式不同之外,下载任务的行为表现的就像一个数据任务。
网友评论