NSURLSession简介与入门

来源:互联网 发布:linux 计算文件大小 编辑:程序博客网 时间:2024/05/21 10:05

       NSURLSession 也不是什么新鲜话题了,但之前一直只是简单的使用却没有总结过其用法及注意事项,现在就整理一下关于NSRULSession的相关知识。

基本组成

       使用需要配合三个基本的对象类型,分别是:

  • NSURLSessionConfiguation
  • NSURLSession
  • NSURLSessionTask

    它们之间的关系,苹果的官方文档有很好的说明:

    To use the NSURLSession API, your app creates a series of sessions, each of which coordinates a group of related data transfer tasks. For example, if you are writing a web browser, your app might create one session per tab or window. Within each session, your app adds a series of tasks, each of which represents a request for a specific URL (and for any follow-on URLs if the original URL returned an HTTP redirect).

    从上面的说明可以看出,NSURLSession类似于平日网络交互时所谓的会话,对于NSURLSession,其本身并不会进行网络数据传输,NSURLSession需要创建若干NSURLSessionTask来对应每次网络数据传输。

    而对于NSURLSessionTask的具体行为,取决于三个方面

  • NSURLSessionde 的类型(由NSURLSessionConfiguation来配置)
  • NSURLSessionTask本身的类型
  • 在Taks创建时,APP是否处于前端(froeground)

NSURLSession的类型

       NSURLSession代表着网络传输中的会话,iOS为其定义了三种不同的类型,并通过NSURLSessionConfiguation进行配置。
        这三种config类型为:

  • Default sessions behave similarly to other Foundation methods for downloading URLs. They use a persistent disk-based cache and store credentials in the user’s keychain.
  • Ephemeral sessions do not store any data to disk; all caches, credential stores, and so on are kept in RAM and tied to the session. Thus, when your app invalidates the session, they are purged automatically.
  • Background sessions are similar to default sessions, except that a separate process handles all data transfers. Background sessions have some additional limitations, described in Background Transfer Considerations.

Default Session 将cache以及credentials存储于本地。
而Ephemeral Session 则对数据更加保密安全一些,它不会向本地存储任何信息,所有的cache、credentials 等存在内存中并和Session绑定,当Session销毁时,所有的相关信息也同时自动销毁。
Background Session能够使APP处于后台时,数据继续传输。其行为与default Session类似,但是所有的数据传输均有一个独立的进程来管理(非本APP)。同时Background Session也有一些功能上的限制。

NSURLSession的创建与配置

对于一个Session,iOS可以设置许多相关的属性:

  • Private storage support for caches, cookies, credentials, and protocols in a way that is specific to a single session
  • Authentication, tied to a specific request (task) or group of requests (session)
  • File uploads and downloads by URL, which encourages separation of the data (the file’s contents) from the metadata (the URL and settings)
  • Configuration of the maximum number of connections per host
  • Per-resource timeouts that are triggered if an entire resource cannot be downloaded in a certain amount of time
  • Minimum and maximum TLS version support
  • Custom proxy dictionaries
  • Control over cookie policies
  • Control over HTTP pipelining behavior

在创建Session对象时,可以通过NSURLSessionConfiguration对象来配置Session,可选的,设置Session的delegate。
Session一旦配置完毕,就不能够修改,除非创建另一个新的Session对象。
示例代码
NSURLSessionConfiguation *defaultConfigObject= [NSURLSessionConfiguation defaultSessionConfiguation];
// 对defaultConfigObject的各种属性进行设置
.....
NSURLSession *session = [NSURLSession sessionWithConfiguration: ephemeralConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];

NSURLSessionTask

       前面说过,要想NSURLSession真正的进行网络传输,则需要在Session下面创建task来进行网络信息传输。
       iOS中有三种类型的task,它们均直接或间接的继承于抽象父类NSURLSessionTask。
       它们关系图如下:

NSURLSessionTask关系图

苹果官方文档对这三种task的描述如下

  • Data tasks send and receive data using NSData objects. Data tasks are intended for short, often interactive requests from your app to a server. Data tasks can return data to your app one piece at a time after each piece of data is received, or all at once through a completion handler.
  • Download tasks retrieve data in the form of a file, and support background downloads while the app is not running.
  • Upload tasks send data in the form of a file, and support background uploads while the app is not running.

DataTask示例
NSURL *url=[NSURL URLWithString:@"www.baidu.com"];
NSURLSessionDataTask *dataTask = [self.session dataTaskWithURL:url];
[dataTask resume];

所有的session task的初始状态都是暂停的,必须使用resume方法启动task。

获取NSURLSession的返回的数据

       由NSURLSession获取响应有两种方式:

  • 在初始化Session对象时,指定NSURLSession对象的delegate
  • 不指定delegate,直接在task创建时指定其complete handler block。

在delegate中获取返回数据。 需要实现两个delegate方法:

  • URLSession:dataTask:didReceiveData: provides the data from a request to your task, one piece at a time.
  • URLSession:task:didCompleteWithError:indicates to your task that the data has been fully received.

利用complete block获取返回数据,则要使用类似如下代码

NSURLSession *delegateFreeSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];
[[delegateFreeSession dataTaskWithURL: [NSURL URLWithString: @"http://www.example.com/"]
completionHandler:^(NSData *data, NSURLResponse *response,
NSError *error) {
NSLog(@"Got response %@ with error %@.\n", response, error);
NSLog(@"DATA:\n%@\nEND DATA\n",
[[NSString alloc] initWithData: data
encoding: NSUTF8StringEncoding]);
}] resume];

注意在上面的两种方法中,都可以获取到NSError对象来获知获取网络数据过程中出现的错误。但是,NSError对象仅会返回client-side的错误,如服务器无法解析,域名错误等。如果想获取来自Server端的错误信息(此时NSError对象为nil),则需要根据NSResponse对象的http status值来获知(对HTTP协议而言)

Authentication Challenges and TLS Chain Validation

        在网络传输中我们经常会收到来自服务器要求授权认证的请求。
        在HTTP协议中,服务端会在response头中包含WWW-Authenticate要求客户端进行认证。在iOS中,会调用响应的delegate方法,让用户对认证请求作出响应。

        对于那些不是来自于WWW-Authenticate的认证要求,iOS不会调用delegate的响应方法对认证要求作出反应。
        对NSURLSession的来说,当URL system loading系统遇到要求客户端认证时,会调用delegate方法:

URLSession:didReceiveChallenge:completionHandler:
URLSession:task:didReceiveChallenge:completionHandler:

NSURLSession 对象的销毁

       当我们不在需要Session对象时,需要将Session对象销毁。可以通过以下两种方法之一:
- (void)invalidateAndCancel
- (void)finishTasksAndInvalidate

invalidateAndCancel 函数会cancel所有的task并释放Session对象的delegate及block,以及Session对象自身。被invalidate的Session对象不能够在复用。

finishTasksAndInvalidate函数会立刻返回,但是不会cancel已经启动的task,而是当这些task完成时,调用delegate的方法:

This method returns immediately without waiting for tasks to finish. Once a session is invalidated, new tasks cannot be created in the session, but existing tasks continue until completion. After the last task finishes and the session makes the last delegate call related to those tasks, the session calls the URLSession:didBecomeInvalidWithError: method on its delegate, then breaks references to the delegate and callback objects. After invalidation, session objects cannot be reused.

这里有个地方需要注意,即:NSURLSession对象对其delegate都是强引用的,只有当Session对象invalidate, 才会释放delegate,否则会出现memory leak。

补充

这里有篇文章,关于NSURLSession的使用问题。我们使用task获取网络数据,而Session则生成这些task。那么,究竟是对每个task都使用一个Session,还是尽量使用同一个Session生成不同的task呢?文章里面给出了答案,对于HTTP协议来说,同一个Session,会复用之前客户端与服务器之间的TCP连接。不用每次都握手,加速了网速(但从该篇文章里面的配图,看不出共享Session下省略的第二次请求的握手????)

别说你会AFNetworking3.0/NSURLSession

参考文献

URL Session Programming Guide

0 0