iOS7新特性-NSURLSession详解
前言:
本文由DevDiv版主@jas 原创翻译,转载请注明出处!
原文:http://www.shinobicontrols.com/b ... day-1-nsurlsession/
大家都知道,过去的IOS系统网络处理是通过NSURLConnection来实现的。由于NSURLConnection通过全局状态来管理cookies和认证信息,这就意味着在某种情况下,可能同时存在两个不同的连接去使用这些公共资源。NSURLSession很好的解决了许多这种类似的问题。
本文连同附件一共讨论了三种不同的下载场景。本文会着重讲述有关NSURLSession的部分,整个项目就不再阐述了。代码可以在github回购。
NSURLSession状态同时对应着多个连接,不像之前使用共享的一个全局状态。会话是通过工厂方法来创建配置对象。
总共有三种会话:
1. 默认的,进程内会话
2. 短暂的(内存),进程内会话
3. 后台会话
如果是简单的下载,我们只需要使用默认模式即可:
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
配置对象有很多属性。例如,可以设置TLS安全等级,TLS决定你可以使用cookies和超时时间。还有两个非常有趣的属性:allowsCellularAccess和discretionary。前一个属性表示当只有一个3G网络时,网络是否允许访问。设置discretionary属性可以控制系统在一个合适的时机访问网络,比如有可用的WiFi,有充足的电量。这个属性主要针对后台回话的,所以在后台会话模式下默认是打开的。
当我们创建了一个会话配置对象后,就可以用它来创建会话对象了:

注意:这里我们把自己设置为代理了。通过代理方法可以告诉我们数据传输进度以及获取认证信息。下面我们会实现一些合适的代理。
数据传输时封装在任务里面的,这里有三种类型:
1. 数据任务 (NSURLSessionDataTask)
2. 上传任务 (NSURLSessionUploadTask)
3. 下载任务(NSURLSessionDownloadTask)
在会话中传输数据时,我们需要实现某一种任务。比如下载:

现在会话将会异步下载此url的文件内容。
我们需要实现一个代理方法来获取这个下载的内容:

这个方法在NSURLSessionDownloadTaskDelegate代理中。在代码中,我们获取到下载文件的临时目录,并把它保存到文档目录下(因为有个图片),然后显示给用户。
上面的代理是下载成功的回调方法。下面代理方法也在NSURLSessionDownloadTaskDelegate代理中,不管任务是否成功,在完成后都会回调这个代理方法。

如果error是nil,则证明下载是成功的,否则就要通过它来查询失败的原因。如果下载了一部分,这个error会包含一个NSData对象,如果后面要恢复任务可以用到。
传输进度
上一节结尾,你可能注意到我们有一个进度来标示每个任务完成度。更新进度条可能不是很容易,会有一个额外的代理来做这件事情,当然它会被调用多次。

这是NSURLSessionDownloadTaskDelegate的另一个代理方法,我们用来计算进度并更新进度条。
取消下载
NSURLConnection一旦发送是没法取消的。但是,我们可以很容易的取消掉一个NSURLSessionTask任务:

非常容易!当取消后,会回调这个URLSession:task:didCompleteWithError:代理方法,通知你去及时更新UI。当取消一个任务后,也十分可能会再一次回调这个代理方法URLSession:downloadTask:didWriteData:BytesWritten:totalBytesExpectedToWrite: 。当然,didComplete 方法肯定是最后一个回调的。
恢复下载
恢复下载也非常容易。这里重写了个取消方法,会生成一个NSData对象,可以在以后用来继续下载。如果服务器支持恢复下载,这个data对象会包含已经下载了的内容。

上面方法中,我们把待恢复的数据保存到一个变量中,方便后面恢复下载使用。
当新创建一个下载任务的时候,除了使用一个新的请求,我们也可以使用待恢复的下载数据:

如果我们有这个partialDownload这个数据对象,就可以用它来创建一个新的任务。如果没有,就按以前的步骤来创建任务。
记住:当使用partialDownload创建任务完成后,需要把partialDownload设置为nil。
后台下载
NSURLSession另一个重要的特性:即使当应用不在前台时,你也可以继续传输任务。当然,我们的会话模式也要为后台模式:

需要非常注意的是,通过给的后台token,我们只能创建一个后台会话,所以这里使用dispatch once block。token的目的是为了当应用重启后,我们可以通过它获取会话。创建一个后台会话,会启动一个后台传输守护进程,这个进程会管理数据并传输给我们。即使当应用挂起或者终止,它也会继续运行。
开启后台下载任务和之前一样,所有的后台功能都是NSURLSession自己管理的。

现在,即使你按home键离开应用,下载也会在后台继续(受开始提到的配置项控制)。
当下载完成后,你的应用将被重启,并传输内容过来。
将会调用app delegate的这个方法:

这里,我们获取内容通过completionHandler,当我们接收下载的数据并更新UI时会调用completionHandler。我们保存了completionHandler(注意需要copy),让正在加载的View Controller来处理数据。当View Controller加载成功后,创建后台会话(并设置代理)。因此之前使用的相同代理方法就会被调用。

需要注意的几个地方:
1. 不能用downloadTask和self.backgroundTask来比较。因为我们不能确定self.backgroundTask是不是已经有了,有可能是应用新的一次重启。比较session是可行的。
2. 这里使用app delegate来获取completion handler 的。其实,有很多方式来获取completion handler 的。
3. 当保存完文件并显示完成后,如果有completion handler,需要移除然后调用。这个是为了告诉系统我们已经完成了,可以处理新的下载任务了。
iOS7新特性-NSURLSession详解的更多相关文章
- JDK19新特性使用详解
前提 JDK19于2022-09-20发布GA版本,本文将会详细介绍JDK19新特性的使用. 新特性列表 新特性列表如下: JPE-405:Record模式(预览功能) JPE-422:JDK移植到L ...
- HTML5新特性及详解
什么是HTML5:HTML5 是下一代的HTML,将成为 HTML.XHTML 以及 HTML DOM 的新标准. 为 HTML5 建立的一些规则: 新特性应该基于 HTML.CSS.DOM 以及 J ...
- Php5.5新特性 Generators详解
在PHP5.5.0版本中,新增了生成器(Generators)特性,用于简化实现迭代器接口(Iterator)创建简单的迭代器的复杂性. 通过生成器,我们可以轻松的使用foreach迭代一系列的数据, ...
- Java8新特性--lamada详解
最近玩了一下这个,感觉挺有趣的,语法使用起来很简洁,让代码看起来挺清爽易读的. 看了一下源码,发现挺充分的利用了jak1.5的特性(注解.泛型). 但是,具体的实现流程还是有点不通透,先Mark,等用 ...
- Servlet3.0新特性使用详解
可插拔的Web框架 几乎所有基于Java的web框架都建立在servlet之上.现今大多数web框架要么通过servlet.要么通过Web.xml插入.利用标注(Annotation)来定义servl ...
- Java8新特性: CompletableFuture详解
CompletableFuture实现了CompletionStage接口和Future接口,前者是对后者的一个扩展,增加了异步回调.流式处理.多个Future组合处理的能力,使Java在处理多任务的 ...
- NSURLSession详解
导语 现在NSURLConnection在开发中会使用的越来越少,iOS9已经将NSURLConnection废弃,现在最低版本一般适配iOS7,所以也可以使用. NSURLConnection相对于 ...
- ios新特征 ARC详解
IOS ARC 分类: IOS ARC2013-01-17 09:16 2069人阅读 评论(0) 收藏 举报 目录(?)[+] 关闭工程的ARC(Automatic Reference Co ...
- IOS7 新特性(针对同样讨厌更新后IOS7的开发者)
本文转载至 http://blog.csdn.net/hanbing861210/article/details/13614211 您还未登录!|登录|注册|帮助 首页 业界 移动 云计算 研发 论坛 ...
随机推荐
- DTrace to Troubleshoot Java Native Memory Problems
How to Use DTrace to Troubleshoot Java Native Memory Problems on Oracle Solaris 11 Hands-On Labs of ...
- centos 6.6编译安装nginx--来自阿里云帮助文档
刚开始接触运维工作, 需要安装nginx,就在网上找了各种的方法, 结果都是大家抄来抄去,都不好用. 由于公司用的是阿里云的服务器, 所以在阿里云上找到了安装nginx的方法,现在摘抄下来,供大家借鉴 ...
- Java基础知识强化之网络编程笔记07:TCP之服务器给客户端一个反馈案例
1. 首先我们搭建服务器端的代码,如下: package cn.itcast_07; import java.io.IOException; import java.io.InputStream; i ...
- RedHat7上安装PHP
编译安装PHP 下载PHP# wget http://cn2.php.net/distributions/php-7.0.0.tar.gz 解压缩PHP# tar -zxvf php-7.0.0.ta ...
- mysql连接错误:Cannot get hostname for your address
问题 环境:win7 + 64Bit + 本地mysql5.6 问题:navicat连接本地mysql数据库,提示“Cannot get hostname for your address”,但是连接 ...
- RelativeLayout相对布局 安卓布局技巧
http://blog.csdn.net/nieweiking/article/details/38417317 RelativeLayout相对布局 相对布局 RelativeLayout 允许子元 ...
- SQL打印全年日历
数据库环境:SQL SERVER 2008R2 我之前有写过打印本月日历的SQL,里头有详细的说明.具体请参考前面的博文——生成本月日历. 全年日历只是在本月日历的基础上加了月信息,并按月份分组求得. ...
- 给分类(Category)添加属性
遇到一个问题,写了一个分类,但原先类的属性不够用.添加一个属性,调用的时候崩溃了,说是找不到getter.setter方法.查了下文档发现,OC的分类允许给分类添加属性,但不会自动生成getter.s ...
- C++ 不使用virtual实现多态
不使用virtual实现多态可以用成员函数指针完成. 成员函数指针形式:返回类型(A::*指针名)(形参表) 其中A是类类型,即这个指针是指向A类的成员函数的函数指针 例如:int(A::*P)(in ...
- .NET中的委托——摘自MSDN
封装一个方法,该方法只有一个参数并且不返回值. 命名空间: System程序集: mscorlib(在 mscorlib.dll 中) 语法 C# public delegate void ...