NSURLSession下载与缓存

NSURLSession下载与缓存

iOS9要求网络请求需要使用NSURLSession,那么本篇文章
就使用NSURLsession来实现视频的下载,图片的下载、取消下载、恢复下
载和缓存功能,期望与大家一起学习。

  • NSURLSessionConfiguration(参数配置类)

    NSURLSession状态同时对应着多个连接,不像之前使用共享的一个全局状态。会话是通过工厂方法(类方法)来创建对象
    NSURLSessionConfiguration

    总共有三种会话:

    1.defaultSessionConfiguration 默认的,进程内会话

    2.ephemeralSessionConfiguration短暂的(内
    存),进程内会话

3.backgroundSessionConfigurationWithIdentifier后台会话

  • 相关属性

    //后台任务的标识符
    
    @property (nullable, readonly, copy) NSString *id entifier;
    
    //缓存的策略
    
    @property NSURLRequestCachePolicy requestCachePolicy;
    
    //请求超时时长
    
    @property NSTimeInterval timeoutIntervalForRequest;
    
    //网络服务类型
    
    @property NSURLRequestNetworkServiceType networkServiceType;
    
    //是否在非无线的情况下请求网络
    
    @property BOOL allowsCellularAccess;
    

手动下载视频

  • 步骤:

    • 在Info.plist中添加NSAppTransportSecurity类型Dictionary。
      在NSAppTransportSecurity下添加NSAllowsArbitraryLoads类型Boolean,值设为YES;

    • 在工程内引入AVFoundation框架,并在相关类引入AVKit、AVFoundation头文件;

    • 遵守NSURLSessionDelegate,NSURLSessionDownloadDelegate协议;

    • 准备一个MP4格式的url,进行下载;

    • 将下载完成的视频资源存入本地,并进行播放。

  • 声明相关属性

 //下载任务  
 @property (nonatomic, strong)NSURLSessionDownloadTask *downTask;  
      
 //网络会话  
 @property (nonatomic, strong)NSURLSession * downLoadSession;
  • 配置相关参数并下载
    //参数设置类  简单的网络下载使用             
      defaultSessionConfiguration即可
    NSURLSessionConfiguration          *sessionConfig =        
    [NSURLSessionConfiguration
    defaultSessionConfiguration];
    
     //创建网络会话  
     self.downLoadSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue new]];
    
    
     //数据请求  
     /*
      *@param URL 资源url  
      *@param timeoutInterval 超时时长
      */
    NSURLRequest *imgRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:MP3URL] cachePolicy:5 timeoutInterval:60.f];
    
     //创建下载任务  
    self.downTask = [self.downLoadSession downloadTaskWithRequest:imgRequest];
    
     //启动下载任务  
    [self.downTask resume];
  • 实现代理方法
  #pragma mark 下载过程

  -(void)URLSession:(NSURLSession *)sessiondownloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
   //获取下载进度
    double currentProgress = totalBytesWritten / (double)totalBytesExpectedToWrite;
    
    dispatch_async(dispatch_get_main_queue(), ^{
       
   //进行UI操作  设置进度条
        
        self.downLoadProgress.progress = currentProgress;
    
    });
    
  #pragma mark 下载完成 无论成功失败

 -(void)URLSession:(NSURLSession *)session task: (NSURLSessionTask *)task didCompleteWithError:(NSError *)error
 {
    
        NSLog(@" function == %s, line == %d, error ==  %@",__FUNCTION__,__LINE__,error);
    
 }
   #pragma mark - 下载成功 获取下载内容
 -(void)URLSession:(NSURLSession *)session   downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
 {
    //存储本地
    
    //1.获取Documents文件夹路径 (不要将视频、音频等较大资源存储在Caches路径下)
        *方法一
        NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) lastObject];
        
        *方法二
        NSFileManager *manager = [NSFileManager defaultManager];
        NSURL * documentsDirectory = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0];
        
   //2.创建资源存储路径
       NSString *appendPath = [NSString stringWithFormat:@"/new.mp4"];
       NSString *file = [documentsPath stringByAppendingString:appendPath];

   //3.将下载好的视频资源存储在路径下
     
      //删除之前相同路径的文件
      BOOL remove  = [manager removeItemAtPath:file error:nil];
      
      //将视频资源从原有路径移动到自己指定的路径
      BOOL success = [manager copyItemAtPath:location.path toPath:file error:nil];

        if (success) {
    
      //回到主线程进行本地视频播放
        dispatch_async(dispatch_get_main_queue(), ^{
            
        //创建视频播放的本地路径
            
        *** 请使用此方法创建本地路径
        NSURL *url = [[NSURL alloc]initFileURLWithPath:file];
           
        *** 此方法创建的路径无法播放 不是一个完整的路径
        //NSURL *url2 = [[NSURL alloc]initWithString:file];
            
        //系统的视频播放器
        AVPlayerViewController *controller = [[AVPlayerViewController alloc]init];
        //播放器的播放类
        AVPlayer * player = [[AVPlayer alloc]initWithURL:url];
            
        controller.player = player;
        //自动开始播放
        [controller.player play];
        //推出视屏播放器
        [self presentViewController:controller animated:YES completion:nil];
                      
            
        });
    }

 }    
  • NSURLSessionDownloadTask支持取消下载,可以在下载过程中随时取消继续下载,同时也可以实现恢复下载。
    • 取消下载 cancelByProducingResumeData

      //用当前NSURLSessionDownloadTask对象去调用取消下载
      
      [self.downTask cancelByProducingResumeData:
       ^(NSData * _Nullable resumeData) {
       
       //全局变量 接收当前下载的资源
       self.data = resumeData;
       }
       //将当前下载任务置为空
       self.downTask = nil;
      
      
    • 恢复下载 downloadTaskWithResumeData

             
      //恢复下载 实际上是建立了一个新的下载任务 去继续之前的下载
            
      self.downTask = [self.downLoadSession downloadTaskWithResumeData:self.data];
        
       //开启任务     
      [self.downTask resume];
            
        }
      

自动缓存

上面讲到的是自己去手动操控整个下载过程,那么,很多伙伴就会讲这样是不是太麻烦了。如果你了解了NSURLSession的缓存策略,那么,你就会发现,我们这么写确实是太麻烦了,那么下面我们就来学习一下NSURsession的自动缓存。

在开始之前,先介绍一下NSURLRequestUseProtocolCachePolicy的几种缓存策略:

  1. NSURLRequestUseProtocolCachePolicy = 0, 默认的缓存策略, 如果缓存不存在,直接从服务端获取。如果缓存存在,
    会根据response中的Cache-Control字段判断下一步操作,如: Cache-Control字段为must-revalidata, 则询问服务端该数据是否有更新,无更新的话直接返回给用户缓存数据,若已更新,则请求服务端.
  1. NSURLRequestReloadIgnoringLocalCacheData = 1, 忽略本地缓存数据,直接请求服务端.
  1. NSURLRequestIgnoringLocalAndRemoteCacheData = 4, 忽略本地缓存,代理服务器以及其他中介,直接请求源服务端.
  1. NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData
  1. NSURLRequestReturnCacheDataElseLoad = 2, 有缓存就使用,不管其有效性(即忽略Cache-Control字段), 无则请求服务端.
  1. NSURLRequestReturnCacheDataDontLoad = 3, 死活加载本地缓存. 没有就失败. (确定当前无网络时使用).

7>NSURLRequestReloadRevalidatingCacheData = 5, 缓存数据必须得得到服务端确认有效才使用(貌似是NSURLRequestUseProtocolCachePolicy中的一种情况)

因此,我们可以根据自己的需求去设置不同的缓存策略,而默认的就是如果有缓存就通过缓存获取数据,没有缓存就去请求网络数据。
这里,我们通过一个请求图片的例子,来窥探一下神奇的自动缓存。

  • 代码:
    //创建一个UIImageView+MyImageView.h的类目,
     //在.h添加一个方法
    - (void)loadIamgeWithURL:(NSString *)urlString
    //在.m去实现此方法  
    - (void)loadIamgeWithURL:(NSString *)urlString
    {
    
    //创建下载图片的url
    NSURL *url = [NSURL URLWithString:urlString];
    
    //创建网络请求配置类
    NSURLSessionConfiguration * configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    
    //创建网络会话
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:nil delegateQueue:[NSOperationQueue new]];
    
    //创建请求并设置缓存策略以及超时时长
    NSURLRequest *imgRequest = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:30.f];
     //*也可通过configuration.requestCachePolicy 设置缓存策略
    
    //创建一个下载任务
    NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:imgRequest completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
       
      //下载完成后获取数据 此时已经自动缓存到本地,下次会直接从本地缓存获取,不再进行网络请求
     NSData * data = [NSData dataWithContentsOfURL:location];
      
      //回到主线程  
    dispatch_async(dispatch_get_main_queue(), ^{
    
      //设置图片      
     self.image = [UIImage imageWithData:data];
     });
        
        
    }];
    
    
    //启动下载任务
    [task resume];
    
    }

通过这种缓存策略,我们就可以实现图片下载并自动缓存,当我们需要再次使用此资源的时候,它就会自动去本地缓存查找是否有已经下载好的图片资源,
如果有就会直接去本地的,从而不需要再去进行网络请求。可以在下载完成后,将网络断开进行测试。

总结

本次主要是讲解了NSURLSession的下载,以及自动缓存策略。它的功能非常强大,还有很多没来得及细细研究,如果你也喜欢它😍,那就抓紧时间去研究吧~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容