NSURLSession的使用

什么是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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容