USURLSession基本使用介绍

USURLSession基本使用介绍

在2013的WWDC上,苹果推出了NSURLConnection的继任者NSURLSession,并且在iOS9.0之后,以前使用的NSURLConnection将提示过期,推荐使用NSURLSession来替换NSURLConnection完成网路请求相关操作。与 NSURLConnection 一样,NSURLSession 指的也不仅是同名类 NSURLSession,还包括一系列相互关联的类。NSURLSession 包括了与之前相同的组件,NSURLRequest 与 NSURLCache,但是把 NSURLConnection 替换成了 NSURLSession、NSURLSessionConfiguration 以及 NSURLSessionTask 的 3 个子类:NSURLSessionDataTask,NSURLSessionUploadTask,NSURLSessionDownloadTask,这三个子类可以直接使用,每个任务都可以挂起(suspend),结束(cancel) 和 执行(resume),调用响应的函数即可
</br>
与 NSURLConnection 相比,NSURLsession 最直接的改进就是可以配置每个 session 的缓存,协议,cookie,以及证书策略(credential policy),甚至跨程序共享这些信息。这将允许程序和网络基础框架之间相互独立,不会发生干扰。每个 NSURLSession 对象都由一个 NSURLSessionConfiguration 对象来进行初始化,后者指定了刚才提到的那些策略以及一些用来增强移动设备上性能的新选项。


1、NSURLSessionDataTask 获取服务器上的数据,返回相关数据,获取后直接处理
2、NSURLSessionUploadTask 创建一个上传任务,在上传时需要制定文件源或数据源,一般来说,对于一个上传任务,也会收到服务的响应也会有相关数据返回,所以NSURLSessionUploadTask继承于NSURLSessionDataTask
3、NSURLSessionDownloadTask 下载服务器上的数据,当任务结束的时候,他会带回一个下载文件的一个临时文件路径,所以在下载大容量任务时,使用尤为方便。
每一个task都是可以取消,暂停或者恢复的。当一个 download task 取消时,可以通过选项来创建一个恢复数据(resume data),然后可以传递给下一次新创建的 download task,以便继续之前的下载,这在断点下载的时候尤为有用。

NSURLSession常用的类

1、NSURL:根据url生成的请求地址
2、NSURLRequest:封装的一个请求,携带发送给服务器的全部数据,里面包含一个NSURL对象,请求方法,请求头,请求体等等。
3、NSMutableURLRequest:这个是NSURLRequest的子类,通过名字我们可以看出这是一个可变的对象,我们可以在这里自定义设置发送的服务器的全部数据(超市等待时间、请求方法、请求体、请求头)
4、NSURLResponse:服务的响应类,和NSURLRequest对象,包含服务返回的响应头部数据
5、NSURLSessionConfiguration 用于配置会话的属性,可以通过该类配置会话的工作模式:
+ (NSURLSessionConfiguration *)defaultSessionConfiguration; 工作模式类似于原来的NSURLConnection,可以使用缓存的Cache,Cookie,鉴权
+ (NSURLSessionConfiguration *)ephemeralSessionConfiguration; 不使用缓存的Cache,Cookie,鉴权。
+ (NSURLSessionConfiguration *)backgroundSessionConfiguration:(NSString *)identifier; 创建一个后台 session,后台 session 不同于常规的,普通的 session,它甚至可以在应用程序挂起,退出或者崩溃的情况下运行上传和下载任务,创建Configuration对象的时候需要给一个NSString的ID用于用于标记后台的session。(稍后详细描述)
6、NSURLSession:会话对象

NSURLSession的使用步骤

1、根据url创建一个NSURL对象
2、根据创建的NSURL创建一个NSURLRequest对象,创建请求对象(此对象内容全部都是默认值,如:请求方法默认是GET),如果想要自定数据则创建NSMutableURLRequest对象
3、创建会话对象NSURLSession,创建NSURLSession对象有三种方法:

1)+ (NSURLSession *)sharedSession; 返回一个默认的NSURLSession,使用共享的会话,该会话使用全局的Cache,Cookie和证书
2)+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration; 返回一个根据刚才创建的Configuration的NSURLSession对象,系统默认创建一个新的OperationQueue处理Session的消息
3)+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue; 返回一个根据刚才创建的Configuration的NSURLSession对象,可以设定回调的delegate(注意这个回调delegate会被强引用),并且可以设定delegate在哪个OperationQueue回调,如果我们将其设置为[NSOperationQueue mainQueue]就能在主线程进行回调非常的方便

4、使用创建好的NSURLSession对象和NSURLRequest对象创建一个NSURLSessionTask任务,NSURLSessionDataTask、NSURLSessionUploadTask 或者 NSURLSessionDownloadTask
5、调用resume开始工作
6、当不再需要连接调用Session的invalidateAndCancel直接关闭,或者调用finishTasksAndInvalidate等待当前Task结束后关闭。这时Delegate会收到URLSession:didBecomeInvalidWithError:这个事件。Delegate收到这个事件之后会被解引用。
</br>
和NSURLConnection一样,NSURLSession也提供了两种形式的使用,代理模式和非代理模式

非代理模式

每个task的构造方法都提供了一个–dataTaskWithRequest:completionHandler:的函数,类似NSURLConnection的sendAsynchronousRequest:queue:completionHandler:sendSynchronousRequest:returningResponse:error:模式,只是NSURLSession仅有异步版本。
例如,如果创建一个NSURLSessionDataTask任务:

    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    self.session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSString *imageURl = @"http://7xt5rm.com2.z0.glb.clouddn.com/picjumbo.com_download.jpg";
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageURl]];
    
    NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request
                                         completionHandler:
     ^(NSData *data, NSURLResponse *response, NSError *error) {
         //接受的数据data、服务器响应response、错误代码error
     }];

    //启动task
    [task resume];
    //其它方法,如取消任务,暂停任务等
    //[task cancel];
    //[task suspend]

再者创建一个NSURLSessionUploadTask任务

    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    self.session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSString *imageURl = @"http://7xt5rm.com2.z0.glb.clouddn.com/picjumbo.com_download.jpg";
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageURl]];
    NSData *data = ...; //上传任务需要一个需要上传的NSData对象或者一个本地文件路径对应的NSURL
    
    NSURLSessionDataTask *uploadTask = [self.session uploadTaskWithRequest:request
                                                            fromData:data
                                                   completionHandler:
     ^(NSData *data, NSURLResponse *response, NSError *error) {
         //接受的数据data、服务器响应response、错误代码error
     }];
     
    //启动task
    [uploadTask resume];
    //其它方法,如取消任务,暂停任务等
    //[uploadTask cancel];
    //[uploadTask suspend];

我们再来看看NSURLSessionDownloadTask任务,下载任务的不同之处在于,NSURLSessionDownloadTask会一点一点的将下载数据写入本地的临时文件,回调block会带回一个下载完成的临时文件的地址,我们需要把文件从这个临时地址移动到文件沙盒中保存起来使用。

    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    self.session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSString *imageURl = @"http://7xt5rm.com2.z0.glb.clouddn.com/picjumbo.com_download.jpg";
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageURl]];
    
    NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request
                                                         completionHandler:
    ^(NSURL *location, NSURLResponse *response, NSError *error) {
        //文件临时地址location,服务器响应response、错误代码error
        //将临时文件移动到app沙盒中
        NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
        NSURL *documentsDirectoryURL = [NSURL fileURLWithPath:documentsPath];
        NSURL *newFileLocation = [documentsDirectoryURL URLByAppendingPathComponent:[[response URL] lastPathComponent]];
        [[NSFileManager defaultManager] copyItemAtURL:location toURL:newFileLocation error:nil];
    }];

    //启动task
    [downloadTask resume];
    //其它方法,如取消任务,暂停任务等
    //[downloadTask cancel];
    //[downloadTask suspend];

代理模式

NSURLSession有几个代理协议NSURLSessionDelegateNSURLSessionTaskDelegateNSURLSessionDataDelegateNSURLSessionDownloadDelegate这几个协议个呈继承关系,NSURLSessionTaskDelegate继承NSURLSessionDelegate,NSURLSessionDataDelegate和NSURLSessionDownloadDelegate继承自NSURLSessionTaskDelegate,实现不同的任务,就实现相应的协议。在这里我们以NSURLSessionDownloadDelegate协议为例:

    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    self.session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSString *imageURl = @"http://7xt5rm.com2.z0.glb.clouddn.com/picjumbo.com_download.jpg";
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageURl]];
    
    //创建下载task
    NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request];
    
    //启动task
    [downloadTask resume];
    //其它方法,如取消任务,暂停任务等
    //[downloadTask cancel];
    //[downloadTask suspend];

代理方法,主要有这么几个:

//当接收到服务器响应的时候调用
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
                                 didReceiveResponse:(NSURLResponse *)response
                                  completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler;

//下载完成之后调用该方法
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                              didFinishDownloadingToURL:(NSURL *)location;

//当接收到下载数据的时候调用,可以在该方法中监听文件下载的进度该方法会被调用多次
//totalBytesWritten:已经写入到文件中的数据大小
//totalBytesExpectedToWrite:目前文件的总大小
//bytesWritten:本次下载的文件数据大小
//可以在此函数中计算下载进度
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                           didWriteData:(int64_t)bytesWritten
                                      totalBytesWritten:(int64_t)totalBytesWritten
                              totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;
//恢复下载的时候调用该方法
//fileOffset:恢复之后,要从文件的什么地方开发下载
//expectedTotalBytes:该文件数据的总大小
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                      didResumeAtOffset:(int64_t)fileOffset
                                     expectedTotalBytes:(int64_t)expectedTotalBytes;

//当请求完成之后调用该方法
//不论是请求成功还是请求失败都调用该方法,如果请求失败,那么error对象有值,否则那么error对象为空
//所有方法之中最后调用
-(void)URLSession:(nonnull NSURLSession *)session task:(nonnull NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error

和NSURLConnection一样我们这里也介绍一下断点下载的相关代码

第一种:每一个task都是有三种状态挂起、执行和取消,所以我们可以在暂停时刻挂起任务,重新下载时执行任务即可
        if (downloadTask.state == NSURLSessionTaskStateSuspended) {
            [downloadTask resume];
        } else {
            [downloadTask suspend];
        }
     但是很多时候不是使用这种方法,不知有哪里不妥。。
第二种:取消的任务的时候保存已下载文件的信息,在恢复下载时,传入此信息。
    //取消下载
    [downloadTask cancelByProducingResumeData:^(NSData * __nullable resumeData) {
        self.resumeData = resumeData;
    }];
    //恢复下载
    downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
    [downloadTask resume];
    比较常用的是这一种。。

后台下载

前面讲到我们可以通过设置NSURLSessionConfiguration的属性BackgroundSession来实现后台下载,在Task执行的时候,用户切到后台,Session会和ApplicationDelegate做交互。当程序切到后台后,在BackgroundSession中的Task还会继续下载。
在切到后台之后,Session的Delegate不会再收到Task相关的消息,直到所有Task全都完成后,系统会调用ApplicationDelegate的application:handleEventsForBackgroundURLSession:completionHandler:回调,之后“汇报”下载工作,对于每一个后台下载的Task调用Session的Delegate中的URLSession:downloadTask:didFinishDownloadingToURL:(成功的话)和URLSession:task:didCompleteWithError:(成功或者失败都会调用)之后调用Session的Delegate回调URLSessionDidFinishEventsForBackgroundURLSession:

看一下代码:
在AppDelegate.m中,加入后台处理函数

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{
    
    self.backgroundTransferCompletionHandler = completionHandler;
    
}

实现delegate的-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session方法

// 后台传输完成,处理URLSession完成事件
-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{
    AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
    
    //检查一下是否所有的下载任务都已经完成
    [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
        if ([uploadTasks count] == 0) {
            if (appDelegate.backgroundTransferCompletionHandler != nil) {
                //在ApplicationDelegate被唤醒后,会有个参数ComplietionHandler,这个参数是个Block,这个参数要在后面Session的Delegate中didFinish的时候调用一下
                
                void(^completionHandler)() = appDelegate.backgroundTransferCompletionHandler;
                appDelegate.backgroundTransferCompletionHandler = nil;
                completionHandler();
            }
        }    
        
    }];
    //执行其他操作
    NSLog(@"All tasks are finished"); 
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • iOS开发系列--网络开发 概览 大部分应用程序都或多或少会牵扯到网络开发,例如说新浪微博、微信等,这些应用本身可...
    lichengjin阅读 3,558评论 2 7
  • NSURLSession 使用步骤使用NSURLSession对象创建Task,然后执行Task -(void)g...
    BEYOND黄阅读 830评论 0 0
  • 在苹果彻底弃用NSURLConnection之后自己总结的一个网上的内容,加上自己写的小Demo,很多都是借鉴网络...
    付寒宇阅读 4,143评论 2 13
  • 直接将view添加到Window上面,[[UIApplication sharedApplication].del...
    AnderQZ阅读 191评论 0 0
  • 自习室告一段落后……………………暧昧 是一种微妙的感觉有所保留又有所突破我喜欢这种感觉我想永远保持这种感觉但世间之...
    纯真阅读 216评论 0 1