NSURLSession的使用

作者: foreverSun_122 | 来源:发表于2016-09-20 23:40 被阅读0次

    什么是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类型如下:

    1. defaultSessionConfiguration
    2. emphemeralSessionConfiguration
    3. backgroundSessionConfiguration

    因此,session的类型也分三种:

    1. 默认Session:基于磁盘建立缓存,将凭证存储在用户的kaychain中
    2. 临时Session:所有高速缓存以及凭证都存储在RAM中,不存储任何数据到磁盘,App无法验证session时将删除RAM中的session数据。
    3. 后台Session:与默认session类似,除了使用一个单独的进程处理所有数据传输外,还有一些其它的限制,具体可参考后台传输的限制小节

    Task类型

    1. 数据任务:使用NSData对象收发数据,主要用于CS之间的临时请求。数据任务可以在每次接收到数据后将数据提交给App,也可以通过处理程序一次将所有数据返回给App。
    2. 下载任务:以文件的形式检索数据,支持后台下载。
    3. 上传任务:以文件形式发送数据,支持后台上传。
    后台Session的限制

    后台Session在进行任务时,实际的数据传输任务由一个单独的进程负责,并且App重启的系统开销较大,所以在使用后台Session时,有如下限制:

    • 仅支持HTTP与HTTPs协议(不支持自定义协议)。
    • 允许重定向。
    • 仅支持文件形式的上传任务(因为从NSData对象和数据流读取数据上传会在程序退出后失败)。
    • 在App进入后台时启动了后台传输,则configuration对象的任意属性被视为true。

    NSCopy行为

    • 在对session对象进行复制时,得到的将是同一个对象。
    • 在对configuration对象进行复制时,得到的将是一个可修改的副本。

    创建和配置Session

    1. 创建一个configuration对象管理session的行为。

    2. 创建一个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请求资源:

    1. 创建configuration对象和相应的session对象。
    2. 在数据被完全接收后,使用处理程序对数据进行处理。

    :系统提供的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下载失败。
    • 三种下载情况:
      1. 如果在后台session中安排下载任务,当App停止运行时还能继续进行下载;当在标准session或临时session中进行下载任务,则会在程序重启后,重新下载。
      2. 用户停止或停止下载时,task调用cancelByProducingResumeData:取消下载,该方法会提供一个resume data用来保存已完成的进度。然后若要在断点处继续进行下载,则将resume data传入到downloadTaskWithResumeData: 或
        downloadTaskWithResumeData:completionHandler:就能新建任务继续下载。
      3. 若数据传输失败(例如任务被取消或者网络中断等),则调用delegate的URLSession:task:didCompleteWithError:方法并附带一个NSError对象,若任务在恢复后可继续进行,则该对象的userInfo字典中包含了键值为NSURLSessionDownloadTaskResumeData的可恢复数据。App就可以通过返回数据到downloadTaskWithResumeData:或
        downloadTaskWithResumeData:completionHandler:重试下载。

    上传请求体内容

    HTTP POST请求的请求体数据来源有三种:NSData对象、文件以及数据流,其使用方式如下:

    1. 数据存储在内存中,且不会被销毁,则可以使用NSData对象作为请求体内容来源
    2. 当上传的内容在磁盘的文件上,或者在后台上传文件,又或者App将为了释放内存中的数据而将数据写入磁盘,这些情况下使用文件作为请求体内容来源
    3. 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:重新创建一个新的流,除了返回数据的方式不同之外,下载任务的行为表现的就像一个数据任务。

    参考文档

    Using NSURLSession

    相关文章

      网友评论

        本文标题:NSURLSession的使用

        本文链接:https://www.haomeiwen.com/subject/buooettx.html