NSURLSession使用注意事项
-
NSURLSession
- 所谓
网络会话
,就是一段同服务器之间的通讯
。一个session
可以由数个数据传输任务
构成。
- session类型由
NSURLSessionConfiguration
对象决定:
-
Default Session / 默认会话
- 功能类似于
NSURLConnection
。
- 磁盘缓存。
- 用
keychain
保存证书。
-
Ephemeral Session / 临时会话
- 内存缓存。
- 不保存证书。
-
invalidate
后,所有信息会被抹去
。
-
Background Session / 后台会话
- app退出后,
数据传输任务
被移动至一个独立的进程中继续执行
。
- 任务在后台执行时,遇到错误会
自动重试
。
- 除了某些限制之外,其它同特性
默认会话
相似。
-
NSURLSessionTask
- 会话期间所执行的
数据传输任务
。
- task类型(所有的task都通过
NSURLSession
创建)
-
NSURLSessionDataTask / 数据任务
- 以
NSData
的形式接收服务器返回的数据
。
-
分段监测
数据。
- 适用于
频繁的短小通讯
。
-
NSURLSessionDownloadTask / 下载任务
- 以
文件
的形式接收服务器返回的数据。
- 解决了大文件下载的
内存管理
问题。
- 能够
断点续传
:
- 其
cancelByProducingResumeData:
会生成一个XML
数据,保存了续传所需的信息
。
- 利用这个数据重新创建
download task
,以继续下载。
- 只有通过
GET
方法获取的文件才可以断点续传。
- 支持
后台下载
。
-
NSURLSessionUploadTask / 上传任务
- 向服务器发送
文件数据
。
- 支持
后台上传
。
- 一般不使用,原因如下:
-
不能
自动封装请求体,即仍然需要手动创建Request body
。
- 如果上传的是
NSData
数据,可以使用POST
方法;但对于磁盘文件
,只能使用PUT
方法,现在基本没有服务器支持这一方法。
-
后台任务
- session必须通过
backgroundSessionConfigurationWithIdentifier:
创建。
- 在一个
独立进程
中执行。
- 必须使用
delegate
实现回调。
- 只支持
HTTP/HTTPs协议
。
- 自动接受
Redirection
。
- 上传任务必须
从文件上传
。
- 如果任务开始时
app处于后台
,那么configuration
对象的discretinary
属性被设置为YES。
/*
后台任务执行流程
*/
(app已退出)后台任务进行中--->
==================================
情况A:任务完成 / 需要验证证书--->
1. app代理方法application:handleEventsForBackgroundURLSession:completionHandler:被调用
2. 在其中所需执行的操作:
- 保存completionHandler
- 根据identifier创建一个background configuration
- 创建background session
--->
3. 后台任务被自动纳入新建session--->
4. 所有任务完成,session代理方法URLSessionDidFinishEventsForBackgroundURLSession:被调用--->
5. 执行之前保存的completionHandler(注意,其属于UIKit,必须在主线程上执行)
==================================
情况B:用户再次启动app--->
1. 在app代理方法application:didFinishLaunchingWithOptions:中根据identifier,创建仍有未完成任务的session对象(一个或多个)
--->
2. 后台任务被自动纳入新建session--->
/*
Session代理方法
*/
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
{
NSLog(@"所有后台任务已经完成");
if (session.configuration.identifier) {
// 执行实现保存的后台session回调
self.backgrondSessionCompletionHandler();
}
}
======================================
/*
app代理方法
*/
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler
{
// 创建配置对象
NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];
// 根据配置对象创建session
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self.sessionDelegate delegateQueue:[NSOperationQueue new]];
NSLog(@"session被重新创建");
// 保存completionHandler
self.backgrondSessionCompletionHandler = completionHandler;
}
-
SSL / TLS 验证
-
Session-Level Challenges / 会话级别验证
,首先尝试调用session代理方法URLSession:didReceiveChallenge:completionHandler:
。其次尝试调用task打理方法URLSession:task:didReceiveChallenge:completionHandler:
。
-
Non-Session-Level Challenges / 非会话级别验证
,只调用task代理方法URLSession:task:didReceiveChallenge:completionHandler:
。
-
注意事项
- session的数据传输任务能且只能
在子线程上执行
。
- 只有NSURLConnection才支持
同步任务
。
- 同时实现
回调block
和代理方法
,默认只调用前者
。
- 如果采用block进行回调,系统会对session进行默认
代理支持
。
- session的
delegate
负责处理session和task级别的回调。
- 用完的session
必须释放
,否则会造成内存泄漏
。因为session会对其delegate
进行强引用
。