NSURLSession

一、URL Session的基本概念

1.三种工作模式:

默认会话模式(default):工作模式类似于原来的NSURLConnection,使用的是基于磁盘缓存的持久化策略,使用用户keychain中保存的证书进行认证授权。

瞬时会话模式(ephemeral):该模式不使用磁盘保存任何数据。所有和会话相关的caches,证书,cookies等都被保存在RAM中,因此当程序使会话无效,这些缓存的数据就会被自动清空。

后台会话模式(background):该模式在后台完成上传和下载,在创建Configuration对象的时候需要提供一个NSString类型的ID用于标识完成工作的后台会话。


2.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新推出的类:

1.NSURLSessionConfiguration类

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

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. + (NSURLSessionConfiguration *)defaultSessionConfiguration;  
  2. + (NSURLSessionConfiguration *)ephemeralSessionConfiguration;  
  3. + (NSURLSessionConfiguration *)backgroundSessionConfiguration:(NSString *)identifier;  

在backgroundSessionConfiguration:方法中的identifier参数指定了会话的ID,用于标记后台的session。

该类的其中两个属性:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* allow request to route over cellular. */  
  2. @property BOOL allowsCellularAccess;  
  3.   
  4. /* allows background tasks to be scheduled at the discretion of the system for optimal performance. */  
  5. @property (getter=isDiscretionary) BOOL discretionary NS_AVAILABLE(NA, 7_0);  

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


2.NSURLSession类

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

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* 
  2.  * The shared session uses the currently set global NSURLCache, 
  3.  * NSHTTPCookieStorage and NSURLCredentialStorage objects. 
  4.  */  
  5. + (NSURLSession *)sharedSession;  
  6.   
  7. /* 
  8.  * Customization of NSURLSession occurs during creation of a new session. 
  9.  * If you only need to use the convenience routines with custom 
  10.  * configuration options it is not necessary to specify a delegate. 
  11.  * If you do specify a delegate, the delegate will be retained until after 
  12.  * the delegate has been sent the URLSession:didBecomeInvalidWithError: message. 
  13.  */  
  14. + (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;  
  15. + (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(id <NSURLSessionDelegate>)delegate delegateQueue:(NSOperationQueue *)queue;  

第一种方式是使用静态的sharedSession方法,该类使用共享的会话,该会话使用全局的Cache,Cookie和证书。

第二种方式是通过sessionWithConfiguration:方法创建对象,也就是创建对应配置的会话,与NSURLSessionConfiguration合作使用。

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


3.NSURLSessionTask类

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

下面是其继承关系:


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

(1)NSURLSessionDataTask

通过request对象或url创建:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* Creates a data task with the given request.  The request may have a body stream. */  
  2. - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;  
  3.   
  4. /* Creates a data task to retrieve the contents of the given URL. */  
  5. - (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url;  

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

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* 
  2.  * data task convenience methods.  These methods create tasks that 
  3.  * bypass the normal delegate calls for response and data delivery, 
  4.  * and provide a simple cancelable asynchronous interface to receiving 
  5.  * data.  Errors will be returned in the NSURLErrorDomain,  
  6.  * see <Foundation/NSURLError.h>.  The delegate, if any, will still be 
  7.  * called for authentication challenges. 
  8.  */  
  9. - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;  
  10. - (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;  

(2) NSURLSessionUploadTask

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

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* Creates an upload task with the given request.  The body of the request will be created from the file referenced by fileURL */  
  2. - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL;  
  3.   
  4. /* Creates an upload task with the given request.  The body of the request is provided from the bodyData. */  
  5. - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData;  
  6.   
  7. /* 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. */  
  8. - (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request;  

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

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* 
  2.  * upload convenience method. 
  3.  */  
  4. - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;  
  5. - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;  


(3)NSURLSessionDownloadTask

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* Creates a download task with the given request. */  
  2. - (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request;  
  3.   
  4. /* Creates a download task to download the contents of the given URL. */  
  5. - (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url;  
  6.   
  7. /* Creates a download task with the resume data.  If the download cannot be successfully resumed, URLSession:task:didCompleteWithError: will be called. */  
  8. - (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;  

下载任务支持断点续传,第三种方式是通过之前已经下载的数据来创建下载任务。
同样地可以通过completionHandler指定任务完成后的回调代码块:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* 
  2.  * download task convenience methods.  When a download successfully 
  3.  * completes, the NSURL will point to a file that must be read or 
  4.  * copied during the invocation of the completion routine.  The file 
  5.  * will be removed automatically. 
  6.  */  
  7. - (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;  
  8. - (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;  
  9. - (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;  


4.NSURLSessionDelegate和NSURLSessionTaskDelegate协议

在协议的方法中可以完成各种各样的回调动作,如身份验证、完成任务后的动作、错误处理和后台任务完成的动作等。委托方法指定在NSURLSession中一定数量的字节传输使用int64_t类型的参数。

这里只说下后台任务的一个委托方法:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* If an application has received an 
  2.  * -application:handleEventsForBackgroundURLSession:completionHandler: 
  3.  * message, the session delegate will receive this message to indicate 
  4.  * that all messages previously enqueued for this session have been 
  5.  * delivered.  At this time it is safe to invoke the previously stored 
  6.  * completion handler, or to begin any internal updates that will 
  7.  * result in invoking the completion handler. 
  8.  */  
  9. - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session NS_AVAILABLE_IOS(7_0);  

合作使用的ApplicationDelegate方法:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. // Applications using an NSURLSession with a background configuration may be launched or resumed in the background in order to handle the  
  2. // completion of tasks in that session, or to handle authentication. This method will be called with the identifier of the session needing  
  3. // attention. Once a session has been created from a configuration object with that identifier, the session's delegate will begin receiving  
  4. // callbacks. If such a session has already been created (if the app is being resumed, for instance), then the delegate will start receiving  
  5. // callbacks without any action by the application. You should call the completionHandler as soon as you're finished handling the callbacks.  
  6. - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler NS_AVAILABLE_IOS(7_0);  

将任务切换到后台之后,Session的Delegate不会再收到和Task相关的消息。当所有Task全都完成后,程序将被唤醒,并调用ApplicationDelegate的application:handleEventsForBackgroundURLSession:completionHandler:回调,在这里要为后台session(由background session的identifier标识)指定对应的回调代码块。

随后,对于每一个完成的后台Task调用该Session的Delegate中的URLSession:downloadTask:didFinishDownloadingToURL:(成功的话)和URLSession:task:didCompleteWithError:(成功或者失败都会调用)方法做处理,以上的回调代码块可以在这里调用。

实战 
这儿我简单的实现了一个下载任务的断点续传功能,具体效果如下: 

 

实现代码如下: 

Object-c代码   收藏代码
  1. #import "UrlSessionDemoViewController.h"  
  2.   
  3. @interface UrlSessionDemoViewController ()  
  4.   
  5. @end  
  6.   
  7. @implementation UrlSessionDemoViewController  
  8.   
  9. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil  
  10. {  
  11.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];  
  12.     return self;  
  13. }  
  14.   
  15. - (void)viewDidLoad  
  16. {  
  17.     [super viewDidLoad];  
  18.     self.progressBar.progress = 0;  
  19. }  
  20.   
  21.   
  22. - (NSURLSession *)session  
  23. {  
  24.     //创建NSURLSession  
  25.     NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];  
  26.     NSURLSession  *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];  
  27.     return session;  
  28. }  
  29.   
  30. - (NSURLRequest *)request  
  31. {  
  32.     //创建请求  
  33.     NSURL *url = [NSURL URLWithString:@"http://p1.pichost.me/i/40/1639665.png"];  
  34.     NSURLRequest *request = [NSURLRequest requestWithURL:url];  
  35.     return request;  
  36. }  
  37.   
  38. -(IBAction)start:(id)sender  
  39. {  
  40.     //用NSURLSession和NSURLRequest创建网络任务  
  41.     self.task = [[self session] downloadTaskWithRequest:[self request]];  
  42.     [self.task resume];  
  43. }  
  44.   
  45. -(IBAction)pause:(id)sender  
  46. {  
  47.     NSLog(@"Pause download task");  
  48.     if (self.task) {  
  49.         //取消下载任务,把已下载数据存起来  
  50.         [self.task cancelByProducingResumeData:^(NSData *resumeData) {  
  51.             self.partialData = resumeData;  
  52.             self.task = nil;  
  53.         }];  
  54.     }  
  55. }  
  56.   
  57. -(IBAction)resume:(id)sender  
  58. {  
  59.     NSLog(@"resume download task");  
  60.     if (!self.task) {  
  61.         //判断是否又已下载数据,有的话就断点续传,没有就完全重新下载  
  62.         if (self.partialData) {  
  63.             self.task = [[self session] downloadTaskWithResumeData:self.partialData];  
  64.         }else{  
  65.             self.task = [[self session] downloadTaskWithRequest:[self request]];  
  66.         }  
  67.     }  
  68.     [self.task resume];  
  69. }  
  70.   
  71. //创建文件本地保存目录  
  72. -(NSURL *)createDirectoryForDownloadItemFromURL:(NSURL *)location  
  73. {  
  74.     NSFileManager *fileManager = [NSFileManager defaultManager];  
  75.     NSArray *urls = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];  
  76.     NSURL *documentsDirectory = urls[0];  
  77.     return [documentsDirectory URLByAppendingPathComponent:[location lastPathComponent]];  
  78. }  
  79. //把文件拷贝到指定路径  
  80. -(BOOL) copyTempFileAtURL:(NSURL *)location toDestination:(NSURL *)destination  
  81. {  
  82.   
  83.     NSError *error;  
  84.     NSFileManager *fileManager = [NSFileManager defaultManager];  
  85.     [fileManager removeItemAtURL:destination error:NULL];  
  86.     [fileManager copyItemAtURL:location toURL:destination error:&error];  
  87.     if (error == nil) {  
  88.         return true;  
  89.     }else{  
  90.         NSLog(@"%@",error);  
  91.         return false;  
  92.     }  
  93. }  
  94.   
  95. #pragma mark NSURLSessionDownloadDelegate  
  96. - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask  
  97. didFinishDownloadingToURL:(NSURL *)location  
  98. {  
  99.     //下载成功后,文件是保存在一个临时目录的,需要开发者自己考到放置该文件的目录  
  100.     NSLog(@"Download success for URL: %@",location.description);  
  101.     NSURL *destination = [self createDirectoryForDownloadItemFromURL:location];  
  102.     BOOL success = [self copyTempFileAtURL:location toDestination:destination];  
  103.       
  104.     if(success){  
  105. //        文件保存成功后,使用GCD调用主线程把图片文件显示在UIImageView中  
  106.         dispatch_async(dispatch_get_main_queue(), ^{  
  107.             UIImage *image = [UIImage imageWithContentsOfFile:[destination path]];  
  108.             self.imageView.image = image;  
  109.             self.imageView.contentMode = UIViewContentModeScaleAspectFit;  
  110.             self.imageView.hidden = NO;  
  111.         });  
  112.     }else{  
  113.         NSLog(@"Meet error when copy file");  
  114.     }  
  115.     self.task = nil;  
  116. }  
  117.   
  118. /* Sent periodically to notify the delegate of download progress. */  
  119. - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask  
  120.       didWriteData:(int64_t)bytesWritten  
  121.  totalBytesWritten:(int64_t)totalBytesWritten  
  122. totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite  
  123. {  
  124.     //刷新进度条的delegate方法,同样的,获取数据,调用主线程刷新UI  
  125.     double currentProgress = totalBytesWritten/(double)totalBytesExpectedToWrite;  
  126.     dispatch_async(dispatch_get_main_queue(), ^{  
  127.         self.progressBar.progress = currentProgress;  
  128.         self.progressBar.hidden = NO;  
  129.     });  
  130. }  
  131.   
  132. - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask  
  133.  didResumeAtOffset:(int64_t)fileOffset  
  134. expectedTotalBytes:(int64_t)expectedTotalBytes  
  135. {  
  136. }  
  137.   
  138. - (void)didReceiveMemoryWarning  
  139. {  
  140.     [super didReceiveMemoryWarning];  
  141. }  
  142.   
  143. @end  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NSURLSessionCorrectedResumeData是一个iOS开发中的类,用于处理网络请求的断点续传功能。 在网络请求过程中,由于各种原因(如网络不稳定或用户手动停止请求),请求可能会中断。为了方便用户继续中断的请求,苹果提供了NSURLSessionCorrectedResumeData来恢复中断的请求。 NSURLSessionCorrectedResumeData是一个二进制数据,它包含了中断请求的具体信息,如请求的URL、请求的方法、请求头信息、请求体等。开发者可以将这个数据保存到本地,以便在下次启动应用时重新发起请求。 当应用再次启动并需要继续中断的请求时,开发者可以使用NSURLSession的resumeData属性来读取之前保存的NSURLSessionCorrectedResumeData数据。 然后,开发者可以通过NSURLSessiondownloadTask(withCorrectedResumeData:completionHandler:)方法来恢复请求。这个方法会根据传入的NSURLSessionCorrectedResumeData创建一个下载任务,并在下载完成后调用回调函数。 需要注意的是,正确使用NSURLSessionCorrectedResumeData需要遵循一些特定的规则。比如,只有之前使用NSURLSessiondownloadTask方法发起的请求才能使用相关的恢复方法,并且不能保证100%的恢复成功。 总结来说,NSURLSessionCorrectedResumeData提供了一种方便的方式来处理网络请求中的断点续传功能,并且提高了用户体验。通过保存和恢复NSURLSessionCorrectedResumeData数据,开发者可以更加灵活地处理中断的请求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值