转载https://blog.csdn.net/u014523377/article/details/51849808/
一.大体步骤
NSURLSession始于ios7.它具有访问接口,上传/下载数据,断点继传和后台下载等功能: 其使用步骤:
1 | 1. 创建session指定其configuration |
二.task分类
session的任务有四种:
1 | 1. 数据任务 Data task |
三. configuration类型
configuration的类型有三种:
1 | 1. 默认配置 Default sessions: |
四.session生成task方式
对于生成每种task的方法,共有4种方式,举downloadTask为例子
1.用urlrequest请求
1 | public func downloadTaskWithRequest(request: NSURLRequest) -> |
2.用url请求
1 | public func downloadTaskWithURL(url: NSURL) -> NSURLSessionDownloadTask1 |
3.带handler的URLRequest请求,注意,如果写了handler,就不会进入代理方法,即使设置了代理也没用
1 | public func downloadTaskWithRequest(request: NSURLRequest, completionHandler: (NSURL?, NSURLResponse?, NSError?) -> Void) -> NSURLSessionDownloadTask1 |
4.带handler的URL请求
1 | public func downloadTaskWithURL(url: NSURL, completionHandler: (NSURL?, NSURLResponse?, NSError?) -> Void) -> NSURLSessionDownloadTask |
五.task分类讲解
下面讲解每种task的具体使用方法
NSURLSession的代理继承关系如图:
NSURLSessionDelegate
|
NSURLSessionTaskDelegate
| | |
NSURLSessionDataDelegate NSURLSessionDownloadDelegate NSURLSessionStreamDelegate
1. 数据任务 Data task
使用:
1 | let config = NSURLSessionConfiguration.defaultSessionConfiguration() |
进入代理方法顺序:
1.首先进入NSURLSessionDataDelegate的didReceiveResponse方法.我们要手动在这里调用completionHandler(.Allow).系统才会继续进入下一步的代理方法,否则到此就结束了
1 | func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) { |
2.然后进入didReceiveData方法,获得json数据,可以做业务操作
1 | func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) { |
3.然后进入didCompleteWithError方法,它是NSURLSessionTaskDelegate的方法,表示请求结束了
1 | func URLSession(session: NSURLSession, task: NSURLSessionTask, error: NSError?) { |
2. 下载任务 Download task
使用:
1 | let config = NSURLSessionConfiguration.defaultSessionConfiguration() |
进入代理方法顺序:
1.NSURLSessionDownloadDelegate的didWriteData,数据正在写入沙盒的tmp文件夹,就会调用这个方法.它是分批次写入的,每写入一段数据就调用这个方法一次,所以会被多次调用
1 | 参数解释: |
1 | func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { |
2.NSURLSessionDownloadDelegate的didFinishDownloadingToURL方法,当数据下载完成后,此时的文件是一个以tmp结尾的文件,命名类似于:
3.进入这个方法didFinishDownloadingToURL.在这里必须执对tmp文件的转移处理,否则当除了这个方法后,tmp文件就被删除了.
1 | func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) { |
4.进入didCompleteWithError方法
1 | func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?){ |
三. 上传
由于上传本人研究不深入,暂时不写,以后更新本节
四. 断点继传
使用:
1 | 注意: |
1 | //经测试这里写backgroundconfig和defaultconfig都可以 |
顺序:
1. 按下中止按钮:
1 | 在回调块中,保存 self.resumeData,便于在继传时使用 |
1 | downloadSessionTask?.cancelByProducingResumeData({ (data:NSData?) in |
如果不按下中止按钮,它进入代理方法的顺序和正常下载是完全一样的.即先进入didWriteData,然后进入didFinishDownloadingToURL,最后didCompleteWithError
如果按下中止按钮,会发生:
1 | 1. 进入didWriteData,毕竟也是写了一些数据的 |
2. 继传
比如我们用一个按钮来启动继传,其中的代码如下:
就是保存的成员变量task 调用downloadTaskWithResumeData方法
1 | @IBAction func clickGoOn(sender: AnyObject) { |
由于downloadTaskWithResumeData也有2种方式,带handler和不带handler的,如果调用了带有handler的那个,则不进入代理方法
进入代理方法的顺序:
1.didResumeAtOffset
1 | func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) { |
2.didWriteData 又开始写入磁盘了
1 | func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { |
3.didFinishDownloadingToURL 这个比较重要,一次下载可以多次中止,但是只有全部写入成功后才会进入这个代理, 在这里将 下载的文件转移走,不然出了这个方法会被删除的
1 | func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) { |
4.didCompleteWithError 这回是真的下载完成了
1 | func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?){ |
四. 后台下载
在下载过程中,如果按home键将app切换到后台,只要不杀死程序,session还能保持其下载能力,完成后,通知到appdelegate的handleEventsForBackgroundURLSession方法.
.虽然app不会因此回到前端
1 | 注意: |
使用:
1 | let config = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(backgroundId) |
进入代理顺序:
1.开始下载时
NSURLSessionDownloadDelegate代理的didWriteData方法
2.按下home,APP进入后台
代理的didWriteData方法不再被进入,而是程序后台静默下载
3.下载完成后
第一步:进入AppDelegate的方法:
1 | func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void) { |
1 | 解释: |
第二步:
进入NSURLSessionDownloadDelegate的didFinishDownloadingToURL方法,请在这里 搬运下载好的tmp文件
第三步:进入didCompleteWithError
第四步:进入NSURLSessionDelegate的URLSessionDidFinishEventsForBackgroundURLSession方法
1 | func URLSessionDidFinishEventsForBackgroundURLSession(session: NSURLSession) |
在第三步或第四步里面, 把从appdelegate里面获取到的handler执行一下,这么做的目的,文档告诉我们是为了让操作系统知道程序可以被继续安全的挂起.