`
啸笑天
  • 浏览: 3435064 次
  • 性别: Icon_minigender_1
  • 来自: China
社区版块
存档分类
最新评论

NSURLSession

 
阅读更多

 

NSURLSession 简介

NSURLConnection这个名字,实际上指的是一组构成Foundation框架中URL加载系统的相互关联的组件:NSURLRequest,NSURLResponse,NSURLProtocol,NSURLCache,NSHTTPCookieStorage,NSURLCredentialStorage,以及和它同名的NSURLConnection。

在WWDC 2013中,Apple的团队对NSURLConnection进行了重构,并推出了NSURLSession作为替代。

NSURLSession也是一组相互依赖的类,它的大部分组件和NSURLConnection中的组件相同如NSURLRequest,NSURLCache等。而NSURLSession的不同之处在于,它将NSURLConnection替换为NSURLSession和NSURLSessionConfiguration,以及3个NSURLSessionTask的子类:NSURLSessionDataTask, NSURLSessionUploadTask, 和NSURLSessionDownloadTask。

NSURLSession 支持 task 特性,NSURLSessionConfiguration 配置对象,以及代理之外还提供了很多关于网络请求的相关特性,比如缓存控制,Cookie 控制,HTTP 验证操作等等。总之 NSURLSession 简单的接口之外,也提供了强大的体系。

 

获取NSURLSession类对象有几种方式:

/* 
 * The shared session uses the currently set global NSURLCache, 
 * NSHTTPCookieStorage and NSURLCredentialStorage objects. 
 */  
+ (NSURLSession *)sharedSession;  
  
/* 
 * Customization of NSURLSession occurs during creation of a new session. 
 * If you only need to use the convenience routines with custom 
 * configuration options it is not necessary to specify a delegate. 
 * If you do specify a delegate, the delegate will be retained until after 
 * the delegate has been sent the URLSession:didBecomeInvalidWithError: message. 
 */  
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;  
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(id <NSURLSessionDelegate>)delegate delegateQueue:(NSOperationQueue *)queue;  

第一种方式是使用静态的sharedSession方法,该类使用共享的会话,该会话使用全局的Cache,Cookie和证书。这个实例是全局共享的,并且功能受限。比如,由于全局实例没有代理对象,我们就不能够检测诸如下载进度这类的事件。以及我们无法设置后台下载的机制,等等。

第二种方式是通过sessionWithConfiguration:方法创建对象,也就是创建对应配置的会话,与NSURLSessionConfiguration合作使用。系统默认创建一个新的OperationQueue处理Session的消息

第三种方式是通过sessionWithConfiguration:delegate:delegateQueue方法创建对象,二三两种方式可以创建一个新会话并定制其会话类型。该方式中指定了session的委托和委托所处的队列。当不再需要连接时,可以调用Session的invalidateAndCancel直接关闭,或者调用finishTasksAndInvalidate等待当前Task结束后关闭。这时Delegate会收到URLSession:didBecomeInvalidWithError:这个事件。Delegate收到这个事件之后会被解引用。(-finishTasksAndInvalidate and -invalidateAndCancel do not  have any effect on the shared session singleton.) 

 

获取NSURLSessionConfiguration类

其中NSURLSessionConfiguration用于配置会话的属性,可以通过该类配置会话的工作模式:

+ (NSURLSessionConfiguration *)defaultSessionConfiguration;  //这个配置会使用全局的缓存,cookie 等信息,这个相当于 NSURLSessionConfiguration 的默认配置行为。

+ (NSURLSessionConfiguration *)ephemeralSessionConfiguration;  //这个配置不会对缓存或 cookie 以及认证信息进行存储,相当于一个私有的 Session,如果你开发一个浏览器产品,这个配置就相当于浏览器的隐私模式。

+ (NSURLSessionConfiguration *)backgroundSessionConfiguration:(NSString *)identifier;  //这个配置可以让你的网络操作在你的应用切换到后台的时候还能继续工作,identifier参数指定了会话的ID,用于标记后台的session。

 

 除了这三种预设的模式之外 NSURLSessionConfiguration 还可以进行很多的配置。NSURLSessionConfiguration中的属性:

 timeoutIntervalForRequest 和 timeoutIntervalForResource 可以控制网络操作的超时时间。 

 allowsCellularAccess 性指定是否允许使用蜂窝连接。

 HTTPAdditionalHeaders 可以指定 HTTP 请求头。

 discretionary属性为YES时表示当程序在后台运作时由系统自己选择最佳的网络连接配置,该属性可以节省通过蜂窝连接的带宽。在使用后台传输数据的时候,建议使用discretionary属性,而不是allowsCellularAccess属性,因为它会把WiFi和电源可用性考虑在内。补充:这个标志允许系统为分配任务进行性能优化。这意味着只有当设备有足够电量时,设备才通过Wifi进行数据传输。如果电量低,或者只仅有一个蜂窝连接,传输任务是不会运行的。后台传输总是在discretionary模式下运行。

 

NSURLSessionConfiguration 几乎可以完成网络操作的大多数配置功能,并且这些配置都绑定到当前的 Session 中,我们一旦用配置好的 NSURLSessionConfiguration 初始化 NSURLSession 实例后,就不能修改这个 NSURLSession 相关的配置了。所以,一切的配置操作都放在初始化 NSURLSession 之前。

 

NSURLSessionTask类

 

NSURLSession 本身是不会进行请求的,而是通过创建 task 的形式进行网络请求(resume() 方法的调用),同一个 NSURLSession 可以创建多个 task,并且这些 task 之间的 cache 和 cookie 是共享的。那么我们就来看看 NSURLSession 都能创建哪些 task 吧。

 

NSURLSessionTask是一个抽象子类,它有三个子类:NSURLSessionDataTask,NSURLSessionUploadTask和NSURLSessionDownloadTask。这三个类封装了现代应用程序的三个基本网络任务:获取数据,比如JSON或XML,以及上传和下载文件。

 

下面是其继承关系:

 

 

NSURLSessionDataTask: 这个就是我们第一个例子中创建的 DataTask,它主要用于读取服务端的简单数据,比如 JSON 数据。

NSURLSessionDownloadTask: 这个 task 的主要用途是进行文件下载,它针对大文件的网络请求做了更多的处理,比如下载进度,断点续传等等。

NSURLSessionUploadTask: 和下载任务对应,这个 task 主要是用于对服务端发送文件类型的数据使用的。

 

看几个例子,比如如何下载文件:

 

let imageURL = NSURL(string: "https://httpbin.org/image/png")!
 
NSURLSession.sharedSession().downloadTaskWithURL(imageURL) { location, response, error in
    
    guard let url = location else { return }
    guard let imageData = NSData(contentsOfURL: url) else { return }
    guard let image = UIImage(data: imageData) else { return }
 
    dispatch_async(dispatch_get_main_queue()) {
        //...
    }

}.resume()

 

 

下载文件的时候,我们使用 downloadTaskWithURL 方法,这个方法的闭包中会接受一个 location 参数,这个参数表示我们下载好的文件的存放位置。

注意,downloadTaskWithURL 会将文件保存在一个临时目录中,location 参数指向这个临时目录的位置,如果我们要将下载好的文件进行持久保存的话,我们还需要将文件从这个临时目录中移动出来。

我们通过 location 参数可以找到文件的位置,然后将文件的内容读取出来,就像我们上面的例子中那样。

 

有多种方法创建对应的任务对象:

 

(1)NSURLSessionDataTask

 

通过request对象或url创建:

 

 /* Creates a data task with the given request.  The request may have a body stream. */  
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;  
  
/* Creates a data task to retrieve the contents of the given URL. */  
- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url;  
 

 

通过request对象或url创建,同时指定任务完成后通过completionHandler指定回调的代码块:

 
/* 
 * data task convenience methods.  These methods create tasks that 
 * bypass the normal delegate calls for response and data delivery, 
 * and provide a simple cancelable asynchronous interface to receiving 
 * data.  Errors will be returned in the NSURLErrorDomain,  
 * see <Foundation/NSURLError.h>.  The delegate, if any, will still be 
 * called for authentication challenges. 
 */  
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;  
- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;  
 

 

(2)NSURLSessionUploadTask

通过request创建,在上传时指定文件源或数据源。

 
 
/* Creates an upload task with the given request.  The body of the request will be created from the file referenced by fileURL */  
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL;  
  
/* Creates an upload task with the given request.  The body of the request is provided from the bodyData. */  
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData;  
  
/* Creates an upload task with the given request.  The previously set body stream of the request (if any) is ignored and the URLSession:task:needNewBodyStream: delegate will be called when the body payload is required. */  
- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request;  
 

 

在创建upload task对象时,通过completionHandler指定任务完成后的回调代码块:

 

 /* 
 * upload convenience method. 
 */  
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;  
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;  
 (3)NSURLSessionDownloadTask

 

 

 /* Creates a download task with the given request. */  
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request;  
  
/* Creates a download task to download the contents of the given URL. */  
- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url;  
  
/* Creates a download task with the resume data.  If the download cannot be successfully resumed, URLSession:task:didCompleteWithError: will be called. */  
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;  
 

 

下载任务支持断点续传,第三种方式是通过之前已经下载的数据来创建下载任务。

同样地可以通过completionHandler指定任务完成后的回调代码块:

 
/* 
 * download task convenience methods.  When a download successfully 
 * completes, the NSURL will point to a file that must be read or 
 * copied during the invocation of the completion routine.  The file 
 * will be removed automatically. 
 */  
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;  
- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;  
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;  
 
 

 

NSURLSessionDelegate的介绍

我们前面的例子都是通过一个闭包在网络操作完成的时候进行处理。那么有什么方法可以监听网络操作过程中发生的事件呢,比如我们下载一个大文件的时候,如果要等到下载完成可能会需要比较长的事件,这时候更好的体验是能够提供一个下载进度。类似这样的事件我们就需要用到代理。

 

我们在使用三种 task 的任意一种的时候都可以指定相应的代理。NSURLSession 的代理对象结构如下:

 

  

NSURLSessionDelegate - 作为所有代理的基类,定义了网络请求最基础的代理方法。

 

NSURLSessionTaskDelegate - 定义了网络请求任务相关的代理方法。

 

NSURLSessionDownloadDelegate - 用于下载任务相关的代理方法,比如下载进度等等。

 

NSURLSessionDataDelegate - 用于普通数据任务和上传任务。

 

我们可以用代理来检测下载进度:

 

class Downloader:NSObject, NSURLSessionDownloadDelegate {

    

    var session: NSURLSession?

    

    override init() {

        

        super.init()

        

        let imageURL = NSURL(string: "https://httpbin.org/image/png")!

        session = NSURLSession(configuration: NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("taask"), delegate: self, delegateQueue: nil)

        session?.downloadTaskWithURL(imageURL).resume()

        

    }

    

    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {

        print("下载完成")

    }

    

    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {

        print("正在下载 \(totalBytesWritten)/\(totalBytesExpectedToWrite)")

    }

    

    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) {

        

        print("从 \(fileOffset) 处恢复下载,一共 \(expectedTotalBytes)")

        

    }

    

    

}

我们的 Downloader 类实现了 NSURLSessionDownloadDelegate 协议,并实现了这个协议的三个方法,分别用于接收下载完成的通知,下载进度变化的通知,以及下载进度恢复的通知。

 

注意,Downloader 同时也继承自 NSObject,这个是必须的,否则我们在实现 NSURLSessionDownloadDelegate 协议的方法时会报错。又由于 NSURLSessionDelegate 继承自 NSObjectProtocol,所以我们需要让 Downloader 继承自 NSObject 类,

这个只有在 Swift 中需要显示的继承,在 Objective-C 中则不需要,因为 Objective-C 中的任何类都是继承自 NSObject 的。

 

 

后台传输服务

 

如果是一个BackgroundSession,在Task执行的时候,用户切到后台,Session会和ApplicationDelegate做交互。当程序切到后台后,在BackgroundSession中的Task还会继续下载,这部分文档叙述比较少,现在分三个场景分析下Session和Application的关系:

 

1、当加入了多个Task,程序没有切换到后台。

  这种情况Task会按照NSURLSessionConfiguration的设置正常下载,不会和ApplicationDelegate有交互。

 

2、当加入了多个Task,程序切到后台,所有Task都完成下载。

  在切到后台之后,Session的Delegate不会再收到,Task相关的消息,直到所有Task全都完成后,系统会调用ApplicationDelegate的application:handleEventsForBackgroundURLSession:completionHandler:回调,之后“汇报”下载工作,对于每一个后台下载的Task调用Session的Delegate中的URLSession:downloadTask:didFinishDownloadingToURL:(成功的话)和URLSession:task:didCompleteWithError:(成功或者失败都会调用)。

 

  之后调用Session的Delegate回调URLSessionDidFinishEventsForBackgroundURLSession:。

 

  注意:在ApplicationDelegate被唤醒后,会有个参数ComplietionHandler,这个参数是个Block,这个参数要在后面Session的Delegate中didFinish的时候调用一下,如下:

 

@implementation APLAppDelegate

 

 

 

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier

 

  completionHandler:(void (^)())completionHandler

 

{

 

    BLog();

 

    /*

 

     Store the completion handler. The completion handler is invoked by the view controller's checkForAllDownloadsHavingCompleted method (if all the download tasks have been completed).

 

     */

 

      self.backgroundSessionCompletionHandler = completionHandler;

 

}

 

//……

 

@end

 

 

 

//Session的Delegate

 

@implementation APLViewController

 

 

 

- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session

 

{

 

    APLAppDelegate *appDelegate = (APLAppDelegate *)[[UIApplication sharedApplication] delegate];

 

    if (appDelegate.backgroundSessionCompletionHandler) {

 

        void (^completionHandler)() = appDelegate.backgroundSessionCompletionHandler;

 

        appDelegate.backgroundSessionCompletionHandler = nil;

 

        completionHandler();

 

    }

 

 

 

    NSLog(@"All tasks are finished");

 

}

 

@end

 

 

 

3、当加入了多个Task,程序切到后台,下载完成了几个Task,然后用户又切换到前台。(程序没有退出)

  切到后台之后,Session的Delegate仍然收不到消息。在下载完成几个Task之后再切换到前台,系统会先汇报已经下载完成的Task的情况,然后继续下载没有下载完成的Task,后面的过程同第一种情况。

 

4、当加入了多个Task,程序切到后台,几个Task已经完成,但还有Task还没有下载完的时候关掉强制退出程序,然后再进入程序的时候。(程序退出了)

 

  最后这个情况比较有意思,由于程序已经退出了,后面没有下完Session就不在了后面的Task肯定是失败了。但是已经下载成功的那些Task,新启动的程序也没有听“汇报”的机会了。经过实验发现,这个时候之前在NSURLSessionConfiguration设置的NSString类型的ID起作用了,当ID相同的时候,一旦生成Session对象并设置Delegate,马上可以收到上一次关闭程序之前没有汇报工作的Task的结束情况(成功或者失败)。但是当ID不相同,这些情况就收不到了,因此为了不让自己的消息被别的应用程序收到,或者收到别的应用程序的消息,起见ID还是和程序的Bundle名称绑定上比较好,至少保证唯一性。

 

Thanks:

http://blog.csdn.net/jymn_chen/article/details/18937819 NSURLSession学习笔记(一)简介

http://www.cnblogs.com/biosli/p/iOS_Network_URL_Session.html NSURLSession使用说明及后台工作流程分析

https://lvwenhan.com/ios/457.html 自己动手写一个 iOS 网络请求库(四)——快速文件上传

http://www.swiftcafe.io/2015/12/20/nsurlsession/ NSURLSession 网络库 - 原生系统送给我们的礼物

https://realm.io/cn/news/gwendolyn-weston-ios-background-networking/?comefrom=http://blogread.cn/news/  应用沉睡之时:后台传输服务

https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSURLSession_class/index.html#//apple_ref/occ/cl/NSURLSession  NSURLSession

http://www.swiftcafe.io/2015/12/23/nsurlsession-app/  使用 NSURLSession 开发一个支持后台下载和断点续传的下载工具

  • 大小: 30.1 KB
  • 大小: 27.4 KB
分享到:
评论
24 楼 啸笑天 2017-01-17  
认证处理策略

当我们进行网络求时,会对相应的认证做出响应。在NSURLSession进行网络请求时支持四种证书处理策略,这些认证处理策略以枚举的形式来存储,枚举的类型为NSURLSessionAuthChallengeDisposition。下方就是认证的所有处理策略:

UseCredential: 使用证书
PerformDefaultHandling: 执行默认处理, 类似于该代理没有被实现一样,credential参数会被忽略
CancelAuthenticationChallenge: 取消请求,credential参数同样会被忽略
RejectProtectionSpace: 拒绝保护空间,重试下一次认证,credential参数同样会被忽略
23 楼 啸笑天 2017-01-17  
1.认证方式

首先我们先来大体的了解一下所有的认证方式

NSURLAuthenticationMethodHTTPBasic: HTTP基本认证,需要提供用户名和密码
NSURLAuthenticationMethodHTTPDigest: HTTP数字认证,与基本认证相似需要用户名和密码
NSURLAuthenticationMethodHTMLForm: HTML表单认证,需要提供用户名和密码
NSURLAuthenticationMethodNTLM: NTLM认证,NTLM(NT LAN Manager)是一系列旨向用户提供认证,完整性和机密性的微软安全协议
NSURLAuthenticationMethodNegotiate: 协商认证
NSURLAuthenticationMethodClientCertificate: 客户端认证,需要客户端提供认证所需的证书
NSURLAuthenticationMethodServerTrust: 服务端认证,由认证请求的保护空间提供信任
上面后两个就是我们在请求HTTPS时会遇到的认证,需要服务器或者客户端来提供认证的,这个证书就是我们平时常说的CA证书。当然你也可以使用自签名证书了,这就不在本篇博客的讨论范围内了。å
22 楼 啸笑天 2017-01-17  
缓存策略概述

在配置网络请求缓存时,有着不同的请求缓存策略。下方就是所有支持的网络缓存策略:

UseProtocolCachePolicy -- 缓存存在就读缓存,若不存在就请求服务器

ReloadIgnoringLocalCacheData -- 忽略缓存,直接请求服务器数据

ReturnCacheDataElseLoad -- 本地如有缓存就使用,忽略其有效性,无则请求服务器

ReturnCacheDataDontLoad -- 直接加载本地缓存,没有也不请求网络

ReloadIgnoringLocalAndRemoteCacheData -- 尚未实现

ReloadRevalidatingCacheData -- 尚未实现

上述缓存策略在Foundation框架中是以枚举的形式来提现的,该缓存策略的枚举类型是NSURLRequestCachePolicy,
21 楼 啸笑天 2017-01-17  
iOS开发之Alamofire源码解析前奏--NSURLSession全家桶
http://www.cnblogs.com/ludashi/p/5556088.html
20 楼 啸笑天 2017-01-17  
知识点

对于NSURLSession对象的初始化需要使用NSURLSessionConfiguration,而NSURLSessionConfiguration有三个类工厂方法:

+defaultSessionConfiguration 返回一个标准的 configuration,这个配置实际上与 NSURLConnection 的网络堆栈(networking stack)是一样的,具有相同的共享 NSHTTPCookieStorage,共享 NSURLCache 和共享NSURLCredentialStorage。

+ephemeralSessionConfiguration 返回一个预设配置,这个配置中不会对缓存,Cookie 和证书进行持久性的存储。这对于实现像秘密浏览这种功能来说是很理想的。

+backgroundSessionConfiguration:(NSString *)identifier 的独特之处在于,它会创建一个后台 session。后台 session 不同于常规的,普通的 session,它甚至可以在应用程序挂起,退出或者崩溃的情况下运行上传和下载任务。初始化时指定的标识符,被用于向任何可能在进程外恢复后台传输的守护进程(daemon)提供上下文。
19 楼 啸笑天 2017-01-16  
[NSURLSession sessionWithConfiguration:configdelegate:selfdelegateQueue:[NSOperationQueuemainQueue]];

参数:delegateQueue:指定回调方法的执行的线程队列。需要注意的是:苹果已经对此方法进行了封装处理。如果直接传值为nil即默认情况下或传进一个并发操作队列即[[NSOperation alloc] init] ,那么执行代理回调方法的队列就是并发队列会由多个线程异步并发执行。但是如果指定为[NSOperation mainQueue],回调方法只会由主线程队列进行同步执行。
18 楼 啸笑天 2017-01-13  
啸笑天 写道
在iOS7以后,系统增加了两种后台的模式,一种是Background fetch ,另一种是Remote notification,下面分别介绍。

Background fetch:  设置了这种后台方式之后,当App休眠之后,会隔一段时间被系统唤醒,从而执行一段短时间操作。唤醒的间隔由系统决定,App中可以设置[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];,但即使设置了,间隔也不确定是多少。另外,App被唤醒后,可以执行操作的时间也不长,文档上描述的30秒左右(实际上更长也可以,但是可能会降低以后被唤醒的几率)。

Remote notification:在iOS7以前,当系统收到推送消息后,会立即弹出消息提示用户,用户点击消息之后,就可以启动App,然后加载数据。使用了这种新的后台模式之后,当系统收到推送消息之后,会唤醒App,给App一个机会执行一部分操作,等操作之后才提醒用户,而且还支持silent模式,即执行完操作之后,完全不对用户做任何提醒,默默的就在后台把活干完了。

除了增加了上述的两种新后台模式以外,ios7还增加了一下传输数据的方法,即Background Transfer service 。

(1)Background Transfer service概述

这种方法的名字很容易让人误解,以为是App进入后台时,使用这种方法进行数据传输。实际上,这种方法与后台无关。 当App使用了这种方法后,可以将一个下载任务交给系统的独立进程去下载,不管App在前台、休眠、以及crash,下载过程都在进行,因为是系统的独立进程在为App进行下载。当系统的下载任务结束或者出错时,系统会唤醒App,调用其中的函数,让App做一部分处理,比如让App重新添加其他任务。这里有一个缺点就是,如果因为没有网络导致系统下载失败了,系统即使唤醒了App,App也是没有办法下载的,然后App会进入休眠,即使后面有了网络,系统也不会继续下载,因为只要系统向App发出了失败的信号,除非App 调用resume函数来恢复下载过程,系统是不会自己恢复下载的。这里就需要用到前面提到的fetch后台模式,让App过一段时间被系统唤醒,然后App就可以去检查网络,当有网时恢复下载过程。


kgroundSessionConfiguration:系统会把上传或下载任务放在单独的进程,允许这些任务在后台进行,及时这个 app 被后台挂起或终止,session 的传输也不会停止(如果你双击home键,向上滑动 app 进行关闭,那么所有的 session 都会中断)
17 楼 啸笑天 2017-01-13  
http://www.cocoachina.com/ios/20160503/16053.html
NSURLSessionDownloadTask的深度断点续传
16 楼 啸笑天 2017-01-13  
NSURLSession使用说明及后台工作流程分析
http://www.cnblogs.com/biosli/p/iOS_Network_URL_Session.html
15 楼 啸笑天 2017-01-13  
使用NSURLSession封装的断点续传
http://www.jianshu.com/p/320daca977bd
14 楼 啸笑天 2017-01-13  
学习 NSURLSession
http://www.jianshu.com/p/377a247a7c12
13 楼 啸笑天 2017-01-13  
和 NSURLConnection 一样,NSURLSession 指的也不仅是同名类 NSURLSession,还包括一系列相互关联的类。NSURLSession 包括了与之前相同的组件,NSURLRequest 与 NSURLCache,但是把 NSURLConnection 替换成了 NSURLSession、NSURLSessionConfiguration 以及 NSURLSessionTask 的 3 个子类:NSURLSessionDataTask,NSURLSessionUploadTask,NSURLSessionDownloadTask。

与 NSURLConnection 相比,NSURLsession 最直接的改进就是可以配置每个 session 的缓存,协议,cookie,以及证书策略(credential policy),甚至跨程序共享这些信息。这将允许程序和网络基础框架之间相互独立,不会发生干扰。每个 NSURLSession 对象都由一个 NSURLSessionConfiguration 对象来进行初始化,后者指定了刚才提到的那些策略以及一些用来增强移动设备上性能的新选项。
12 楼 啸笑天 2017-01-13  
在iOS7以后,系统增加了两种后台的模式,一种是Background fetch ,另一种是Remote notification,下面分别介绍。

Background fetch:  设置了这种后台方式之后,当App休眠之后,会隔一段时间被系统唤醒,从而执行一段短时间操作。唤醒的间隔由系统决定,App中可以设置[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];,但即使设置了,间隔也不确定是多少。另外,App被唤醒后,可以执行操作的时间也不长,文档上描述的30秒左右(实际上更长也可以,但是可能会降低以后被唤醒的几率)。

Remote notification:在iOS7以前,当系统收到推送消息后,会立即弹出消息提示用户,用户点击消息之后,就可以启动App,然后加载数据。使用了这种新的后台模式之后,当系统收到推送消息之后,会唤醒App,给App一个机会执行一部分操作,等操作之后才提醒用户,而且还支持silent模式,即执行完操作之后,完全不对用户做任何提醒,默默的就在后台把活干完了。

除了增加了上述的两种新后台模式以外,ios7还增加了一下传输数据的方法,即Background Transfer service 。

(1)Background Transfer service概述

这种方法的名字很容易让人误解,以为是App进入后台时,使用这种方法进行数据传输。实际上,这种方法与后台无关。 当App使用了这种方法后,可以将一个下载任务交给系统的独立进程去下载,不管App在前台、休眠、以及crash,下载过程都在进行,因为是系统的独立进程在为App进行下载。当系统的下载任务结束或者出错时,系统会唤醒App,调用其中的函数,让App做一部分处理,比如让App重新添加其他任务。这里有一个缺点就是,如果因为没有网络导致系统下载失败了,系统即使唤醒了App,App也是没有办法下载的,然后App会进入休眠,即使后面有了网络,系统也不会继续下载,因为只要系统向App发出了失败的信号,除非App 调用resume函数来恢复下载过程,系统是不会自己恢复下载的。这里就需要用到前面提到的fetch后台模式,让App过一段时间被系统唤醒,然后App就可以去检查网络,当有网时恢复下载过程。

11 楼 啸笑天 2017-01-13  
iOS后台下载功能(收集)
http://www.jianshu.com/p/15d97c6a4f7f
10 楼 啸笑天 2017-01-13  
NSURLSession的使用
http://www.jianshu.com/p/5ec3fa8f8cee
9 楼 啸笑天 2017-01-13  
创建和配置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
8 楼 啸笑天 2017-01-13  
NSCopy行为

在对session对象进行复制时,得到的将是同一个对象。
在对configuration对象进行复制时,得到的将是一个可修改的副本。
7 楼 啸笑天 2017-01-13  
后台Session的限制

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

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

数据任务:使用NSData对象收发数据,主要用于CS之间的临时请求。数据任务可以在每次接收到数据后将数据提交给App,也可以通过处理程序一次将所有数据返回给App。
下载任务:以文件的形式检索数据,支持后台下载。
上传任务:以文件形式发送数据,支持后台上传。
5 楼 啸笑天 2017-01-12  
【补充】NSURLSession 详解离线断点下载的实现
http://www.jianshu.com/p/b63217ff7287

相关推荐

Global site tag (gtag.js) - Google Analytics