美文网首页
NSURLSession

NSURLSession

作者: coder_jie | 来源:发表于2017-05-12 00:42 被阅读0次

    一、NSURLSession概览

    1 NSURLSession的类型

    • 默认会话(Default Sessions)使用了持久的磁盘缓存,并且将用户的证书存入钥匙串
    • 临时会话(Ephemeral Sessions)没有向磁盘中存入任何数据,所有相关内容都存在RAM中,当会话无效时,证书及缓存的数据都会被清除掉。
    • 后台会话(Background Sessions)除了使用了一个单独的线程来处理会话之外,与默认会话类似。但使用后台会话有一些限制,比如会话必须提供事件交付的代理方法、只有HTTP和HTTPS协议支持后台会话、总是伴随着重定向。仅仅在上传文件时才支持后台会话,当你上传二进制对象或者数据流时是不支持后台会话的。当App进入后台时,后台传输就会被初始化。(需要注意的是iOS8和OS X 10.10之前的版本中后台会话是不支持数据任务(data task)的)

    会话的类型都要通过NSURLSessionConfiguration来指定
    NSURLSessonConfiguration的创建

    //默认会话
        NSURLSessionConfiguration* defaultSessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    //临时会话
        NSURLSessionConfiguration* ephemeralSessionConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
    //后台会话
        NSURLSessionConfiguration* backgroundSessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"bacjgroundID"];
    
    
    + (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;
    
    + (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;
    
    

    2 NSURLSession的各种任务

    在一个Session会话中可以发起的任务分为三种:数据任务(Data task),下载任务(Download task),上传任务(Upload task)。

    • Data Task(数据任务)负责使用NSData对象来发送和接收数据。Data Task是为了那些简短的并且经常从服务器请求的数据而准备的。该任务可以没请求一次就对返回的数据进行一次处理。
    • Download task(下载任务)以表单的形式接收一个文件的数据,该任务支持后台下载。
    • Upload task(上传任务)以表单的形式上传一个文件的数据,该任务同样支持后台下载。

    二.RUL编码

    1 概述

    1.URL编码概述

    无论是GET、POST还是其他的请求,与服务器交互的URL是需要进行编码的。因为进行URL编码的参数服务器那边才能进行解析,为了能和服务器正常的交互,我们需要对我们的参数进行转义和编码。先简单的聊一下什么是URL吧,其实URL是URI(Uniform Resource Identifier ---- 统一资源定位符)的一种。URL就是互联网上资源的地址,用户可以通过URL来找到其想访问的资源。RFC3986文档规定,<font color = red>Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符,</font>如果你的URL中含有汉字,那么就需要对其进行转码了。<font color = red>RFC3986中指定了以下字符为保留字符:! * ' ( ) ; : @ & = + $ , / ? # [ ]。</font>

    在URL编码时有一定的规则,在Get请求中Query是存放在URL后边,而在POST中是放在Request的Body中。如果你的参数只是一个<font color = red>key-Value</font>, 那么Query的形式就是key = value。如果你的参数是一个数组比如<font color = red>key = [itme1, item2, item3,……]</font>,那么你的Query的格式就是<font color = red>key[]=item1&key[itme2]&key[item3]……</font>。如果你的参数是一个字典比如<font color = red>key = ["subKey1":"item1", "subKey2":"item2"]</font>, 那么Query对应的形式就是<font color = red>key[subKey1]=item1&key[subKey2]=item2</font>.接下来我们要做的就是将字典进行URL编码。

    2.编码

    AFNetworking中对应的编码如下:

    
    NSString * AFQueryStringFromParameters(NSDictionary *parameters) {
        NSMutableArray *mutablePairs = [NSMutableArray array];
        for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) {
            [mutablePairs addObject:[pair URLEncodedStringValue]];
        }
    
        return [mutablePairs componentsJoinedByString:@"&"];
    }
    
    NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary) {
        return AFQueryStringPairsFromKeyAndValue(nil, dictionary);
    }
    
    NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
        NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
    
        NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)];
    
        if ([value isKindOfClass:[NSDictionary class]]) {
            NSDictionary *dictionary = value;
            // Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries
            for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
                id nestedValue = dictionary[nestedKey];
                if (nestedValue) {
                    [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
                }
            }
        } else if ([value isKindOfClass:[NSArray class]]) {
            NSArray *array = value;
            for (id nestedValue in array) {
                [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
            }
        } else if ([value isKindOfClass:[NSSet class]]) {
            NSSet *set = value;
            for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
                [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue(key, obj)];
            }
        } else {
            [mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
        }
    
        return mutableQueryStringComponents;
    }
    
    

    三、数据任务--NSURLSesionDataTask

    NSURLSessionDataTask的使用步骤

    • 首先我们先创建会话使用的URL,在创建URL是我们要对parameters字典参数进行URL编码。如果是GET方式的请求的话就使用?号将我们编码后的字符串拼接到URL后方即可。
    • 然后创建我们会话使用的请求(NSURLMutableRequest),在创建请求时我们要指定请求方式是POST还是GET。如果是POST方式,我们就将编码后的URL字符串放入request的HTTPBody中即可,有一点需要注意的是我们传输的数据都是二进制的,所以在将字符串存入HTTPBody之前要将其转换成二进制,在转换成二进制的同时我们使用的是UTF8这种编码格式。
    • 创建完Request后,我们就该创建URLSession了,此处我们为了简单就获取了全局的Session单例。我们使用这个Session单例创建了含有Request对象的一个DataTask。在这个DataTask创建时,有一个尾随闭包,这个尾随闭包用来接收服务器返回来的数据。当然此处可以指定代理,使用代理来接收和解析数据的,稍后会介绍到。
    • 最后切记创建好的Data Task是处于挂起状态的,需要你去唤醒它,所以我们要调用dataTask的resume方法进行唤醒。具体如下所示。
        NSString* baseUrlStr = [NSString stringWithUTF8String:"www.baidu.com"];
        
        NSURL* url = [NSURL URLWithString:baseUrlStr];
        
        NSMutableURLRequest* mutableRequest = [NSMutableURLRequest requestWithURL:url];
        
        //设置请求方式
        mutableRequest.HTTPMethod = @"GET";
        
        //参数编码
        
        //拼接参数
        //get 用 ?
        //post httpbody
        
        
        //创建data task
        NSURLSessionDataTask* dataTask = [self.session dataTaskWithRequest:mutableRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        }];
        
        //唤起
        [dataTask resume];
        
    

    四、上传任务 --- Upload Task

    NSURLSessionUploadTask的使用步骤:

    • 先创建URL和request并为request指定请求方式为POST
    • 然后创建Session,此处我们使用SessionConfiguration为Session的类型指定为default session类型。并为该Session指定代理对象为self。
    • 最后使用Session来创建upload task,在创建upload task时为上传任务指定NSURLRequest对象,并且传入要上传的表单数据formData,当然不要忘了将任务进行唤醒。
        NSString* baseUrlStr = [NSString stringWithUTF8String:"www.baidu.com"];
        
        NSURL* url = [NSURL URLWithString:baseUrlStr];
        
        NSMutableURLRequest* mutableRequest = [NSMutableURLRequest requestWithURL:url];
        
        //设置请求方式
        mutableRequest.HTTPMethod = @"POST";
        //参数编码
        
        //拼接参数
        //post httpbody
        
        //上传文件的数据
        NSString* uploadStr = @"this is a upload str";
        NSData* uploadData = [uploadStr dataUsingEncoding:NSUTF8StringEncoding];
        
        NSURLSessionUploadTask* uploadTask = [self.session uploadTaskWithRequest:mutableRequest fromData:uploadData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            
        }];
        
        //唤醒
        [uploadTask resume];
    

    备注:
    在上传文件时,如果你想时刻的监听上传的进度,你可以去实现NSURLSessionTaskDelegate中的didSendBodyData方法,该方法会实时的监听文件上传的速度。

    bytesSent回调参数表示本次上传的字节数,
    totalBytesSend回调参数表示已经上传的数据大小,totalBytesExpectedToSend表示文件公有的大小。

    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
    

    五、下载任务--Download Task

    1.创建后台会话

        NSURLSessionConfiguration* backgroundSessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"bacjgroundID"];
        
        self.session = [NSURLSession sessionWithConfiguration:backgroundSessionConfiguration delegate:self delegateQueue:queue];
    

    2.开始下载

        NSURLSessionConfiguration* backgroundSessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"bacjgroundID"];
        
        self.session = [NSURLSession sessionWithConfiguration:backgroundSessionConfiguration delegate:self delegateQueue:nil];
        
        
        if (self.resumeData) {
            //如果有已下载的数据
            self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                //Block下载方式不适合大文件下载
                
                //接收数据
                //确定文件路径
                //剪切文件
            }];
        }else{
            //没下载过
            NSString* baseUrlStr = [NSString stringWithUTF8String:"www.baidu.com"];
            
            NSURL* url = [NSURL URLWithString:baseUrlStr];
            
            NSMutableURLRequest* mutableRequest = [NSMutableURLRequest requestWithURL:url];
            
            //设置请求方式
            mutableRequest.HTTPMethod = @"POST";
            //参数编码
            
            //拼接参数
            //post httpbody
            
            //上传文件的数据
            NSString* uploadStr = @"this is a upload str";
            NSData* uploadData = [uploadStr dataUsingEncoding:NSUTF8StringEncoding];
            
            self.downloadTask = [self.session downloadTaskWithRequest:mutableRequest completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                //Block下载方式不适合大文件下载
                
                //接收数据
                //确定文件路径
                //剪切文件
                
            }];
        }
        [self.downloadTask resume];
    

    推荐使用代理方法来处理下载

    3.下载的暂停与恢复

    //取消下载(不可以恢复)
    - (void)cancleDownLoad
    {
        [self.downloadTask cancel];
    }
    //可以恢复下载
    - (void)cancleByResumeData
    {
        [self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
            self.resumeData = resumeData;
        }];
    }
    //挂起下载
    - (void)suspendDownLoad
    {
        [self.downloadTask suspend];
    }
    //回复继续下载
    - (void)resumeDownLoad
    {
        [self.downloadTask resume];
    }
    
    

    4.下载任务的回调

    NSURLSessionDownloadDelegate中的方法

    /**
     下载完成
    
     @param session session对象
     @param downloadTask downloadTask对象
     @param location 临时文件的下载目录
     */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
    {
        //临时文件在下载完成之后如果你不做任何处理的话,那么就会被自动删除
        
        //创建文件存储路径
        //移动临时文件
    }
    
    
    /**
     下载文件偏移,主要用于断点续传
    
     @param session session对象
     @param downloadTask downloadTask对象
     @param fileOffset 已经下载文件的大小
     @param expectedTotalBytes 文件的总大小
     */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
    {
        //更新下载进度条
    }
    
    
    
    /**
     实时监听下载任务回调
    
     @param session session对象
     @param downloadTask downloadTask对象
     @param bytesWritten 本次下载的数据
     @param totalBytesWritten 已经下载的数据总量
     @param totalBytesExpectedToWrite 文件的总量
     */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
    {
        //更新下载进度条
    }
    
    //后台下载完成之后的操作
    - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
    {
        //配合application:handleEventsForBackgroundURLSession:completionHandler:方法使用
    }
    
    
    //当NSURLSession在后台开启几个任务之后, 如果有其他几个任务完成后系统会调用应用程序的
    - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler
    {
        
    }
    

    NSURLSessionTaskDelegate中的方法

    //任务完成 不管是不是下载都会调用
    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
    {
        
    }
    

    六、网络缓存

    网络缓存在网络请求中使用的还是蛮多的,尤其是加载一些H5页面时经常会加一些缓存来提高用户体验。有时的一些数据也会进行缓存,你可将数据缓存到你的SQLite数据库、PList文件,或者直接使用NSURLSession相关的东西进行缓存。

    1、缓存策略

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

    • NSURLRequestUseProtocolCachePolicy -- 缓存存在就读缓存,若不存在就请求服务器
    • NSURLRequestReloadIgnoringLocalCacheData -- 忽略缓存,直接请求服务器数据
    • NSURLRequestReturnCacheDataElseLoad -- 本地如有缓存就使用,忽略其有效性,无则请求服务器
    • NSURLRequestReturnCacheDataDontLoad -- 直接加载本地缓存,没有也不请求网络
    • NSURLRequestReloadIgnoringLocalAndRemoteCacheData -- 尚未实现
    • NSURLRequestReloadRevalidatingCacheData -- 尚未实现

    2、NSMutableURLRequest指定缓存策略

    mutableRequest.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData
    
    

    缓存目录默认为~/Library/Caches/[Boundle ID]/fsCachedData/缓存文件

    3、NSURLSessionConfiguration指定缓存策略

        SessionConfiguration.requestCachePolicy = NSURLRequestReloadIgnoringCacheData;
    
    

    4、NSURLCache + request进行缓存

        NSInteger memoryCapacity = 4 * 1024 * 1024;
        NSInteger diskCapacity = 10 * 1024 * 1024;
        NSString* cacheFilePath = @"myCache";
        
        NSURLCache* urlCache = [[NSURLCache alloc] initWithMemoryCapacity:memoryCapacity diskCapacity:diskCapacity diskPath:cacheFilePath];
        [NSURLCache setSharedURLCache:urlCache];
    

    有一点需要注意的是此处设置的缓存路径是相对于/Library/Caches/[Boundle ID]/的

    5、NSURLCache +SessionConfiguration进行缓存

        SessionConfiguration.requestCachePolicy = NSURLRequestReloadIgnoringCacheData;
        NSInteger memoryCapacity = 4 * 1024 * 1024;
        NSInteger diskCapacity = 10 * 1024 * 1024;
        NSString* cacheFilePath = @"myCache";
        
        NSURLCache* urlCache = [[NSURLCache alloc] initWithMemoryCapacity:memoryCapacity diskCapacity:diskCapacity diskPath:cacheFilePath];
        SessionConfiguration.URLCache = urlCache;
    

    6、清除缓存

    NSFileManager removeItemAtPath

    七、请求认证

    1.认证方式

    • NSURLAuthenticationMethodHTTPBasic: HTTP基本认证,需要提供用户名和密码
    • NSURLAuthenticationMethodHTTPDigest: HTTP数字认证,与基本认证相似需要用户名和密码
    • NSURLAuthenticationMethodHTMLForm: HTML表单认证,需要提供用户名和密码
    • NSURLAuthenticationMethodNTLM: NTLM认证,NTLM(NT LAN Manager)是一系列旨向用户提供认证,完整性和机密性的微软安全协议
    • NSURLAuthenticationMethodNegotiate: 协商认证
    • NSURLAuthenticationMethodClientCertificate: 客户端认证,需要客户端提供认证所需的证书
    • NSURLAuthenticationMethodServerTrust: 服务端认证,由认证请求的保护空间提供信任

    后两个就是我们在请求HTTPS时会遇到的认证,需要服务器或者客户端来提供认证的,这个证书就是我们平时常说的CA证书.

    2.认证处理策略

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

    • NSURLSessionAuthChallengeUseCredential 使用证书
    • NSURLSessionAuthChallengePerformDefaultHandling 执行默认处理, 类似于该代理没有被实现一样,credential参数会被忽略
    • NSURLSessionAuthChallengeCancelAuthenticationChallenge 取消请求,credential参数同样会被忽略
    • NSURLSessionAuthChallengeRejectProtectionSpace 拒绝保护空间,重试下一次认证,credential参数同样会被忽略

    3.HTTPS请求证书处理

    发起上述https请求后,就会执行下方的代理方法。下方的委托代理方法属于NSURLSessionDelegate中处理认证的方法,也就是如果服务器需要认证时就会执行下方的回调方法。下方代码首先从授权质疑的保护空间中取出认证方式,然后根据不同的认证方式进行不同的处理。下方给出了两种认证方式的处理,上面的if语句块赋值服务端认证,下面的if语句块负责HTTP的基本认证。具体处理方式如下所示。有一点需要注意的是如果在该委托回调方法中如果不执行completionHandler闭包,那么认证就会失效,是请求不到数据的。

    
    /**
     服务器需要验证时会触发
    
     @param session session对象
     @param challenge 授权质疑
     @param completionHandler block
     */
    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler {
        
        // 判断是否是信任服务器证书
        if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
            //https
            // 告诉服务器,客户端信任证书
            // 创建凭据对象
            NSURLCredential *credntial = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            // 通过completionHandler告诉服务器信任证书
            completionHandler(NSURLSessionAuthChallengeUseCredential,credntial);
        }
        /**
          * HTTP BASE
         */
        if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic) {
            NSURLCredential *credntial = [[NSURLCredential alloc] initWithUser:@"username" password:@"password" persistence:NSURLCredentialPersistenceForSession];
            completionHandler(NSURLSessionAuthChallengeUseCredential,credntial);
        }
        //取消请求
        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,nil);
    }
    

    八、NSURLSession相关代理

    1、NSURLSessionDelegate

    1. didReceiveChallenge
      其他
    //Session无效后被调用
    - (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error
    {
        
    }
    //后台Session在执行完后台任务后所执行的方法
    - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
    {
        
    }
    

    2、NSURLSessionTaskDelegate

    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
    willPerformHTTPRedirection:(NSHTTPURLResponse *)response
            newRequest:(NSURLRequest *)request
     completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler;
    {
        
    }
    

    3、NSURLSessionDataDelegate

    NSURLSessionDataDelegate中的方法主要是用来处理Data Task任务相应的事件的

    1、相应处理策略

    • NSURLSessionResponseCancel 取消数据的加载,默认为 Cancel。此处理方式就是忽略数据的加载,取消对响应数据的进一步解析
    • NSURLSessionResponseAllow 允许继续操作, 会执行 NSURLSessionDataDelegate中的dataTaskDidReceiveData回调方法
    • NSURLSessionResponseBecomeDownload 将Data Task的响应转变为DownloadTask,会执行NSURLSessionDownloadDelegate代理中相应的方法
    • NSURLSessionResponseBecomeStream 将Data Task的响应转变为DownloadTask,会执行NSURLSessionStreamDelegate代理中相应的方法

    2.代理方法

    /**
     收到响应时会执行的方法
    
     @param session session
     @param dataTask dataTask
     @param response 服务器响应
     @param completionHandler block
     */
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
    didReceiveResponse:(NSURLResponse *)response
     completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
    {
        //处理策略设置成Allow后会执行下方的方法,如果响应处理策略不是Allow那么就不会接收到服务器的Data
    }
    
    /**
     接收数据后会执行的方法
     
     @param session session
     @param dataTask dataTask
     @param data 接收的数据
     */
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
        didReceiveData:(NSData *)data
    {
        
    }
    
    /**
     任务转变为下载时所执行的方法
    
     @param session session
     @param dataTask dataTask
     @param downloadTask downloadTask
     */
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
    didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
    {
        
    }
    
    /**
     任务转变为streamTask时所执行的方法
    
     @param session session
     @param dataTask dataTask
     @param streamTask streamTask
     */
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
    didBecomeStreamTask:(NSURLSessionStreamTask *)streamTask
    {
        //iOS9
    }
    
    
    /**
     将要进行缓存时执行的方法
    
     @param session session
     @param dataTask dataTask
     @param proposedResponse streamTask
     @param completionHandler block
     */
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
     willCacheResponse:(NSCachedURLResponse *)proposedResponse
     completionHandler:(void (^)(NSCachedURLResponse * _Nullable cachedResponse))completionHandler
    {
        
    }
    

    相关文章

      网友评论

          本文标题:NSURLSession

          本文链接:https://www.haomeiwen.com/subject/lkwmtxtx.html