zoukankan      html  css  js  c++  java
  • iOS NSURLSession 封装下载类

      周六日鼓捣NSURLSession,效率虽然低下,最后还是有了一点点眉目。昨天和汤老师一起测试,又对它加深了一点理解。趁热打铁,先总结一下。

      封装的类,对外用的方法,我写的是类方法,所以,在类方法中,就不能调用本身的@property变量了。解决办法是:将本身的类先定义为单例,在利用单例将本身的属性方法调用出来。

      0.准备工作

      工具类必须先遵守DownloadDelegate,同时建立一个session的属性方法

    @property(nonatomic, strong)NSURLSession * downloadSession;

      1.单例的构造方法:

    +(DownloadTool *)instance{   //DownloadTool是当前封装类的名字
        static DownloadTool * aInstance = nil;
        static dispatch_once_t  once_token;
        dispatch_once(&once_token, ^{
            aInstance = [[DownloadTool alloc]init];
            aInstance.downloadDic = [NSMutableDictionary dictionary]; //这个是本身的一个@property属性变量,放在这个里面进行初始化
        });
        return aInstance;
    }
    

      单例构造完成,在类方法里面,我们就可以使用单例来调出属性变量。

      2.单一session的构造方法

    /**
     *  创建session
     */
    - (NSURLSession *)isDownloadSession{
        if (!_downloadSession) {
            NSString * configurationStr = @"DownloadTool";
            NSURLSessionConfiguration * sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:configurationStr];
            NSURLSession * downloadSession = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
            _downloadSession = downloadSession; //_downloadSession是前面定义的属性方法
        }
        return _downloadSession;
    }
    

      session用configuration来唯一标示,可以用identifier来唯一标识,和其他的不同的session来区分,如果整个项目的session用的是同一个的话,可以用shareSession单例。代理设置为self,Queue,一般设置为主线程。

      3.开始下载--这个可以定义类的调用方法里面,自己定义,同时将URL传入进来即可

        if ([[DownloadTool instance]isDownloadSession]) {
            NSURLSessionDownloadTask * downloadTask = [[DownloadTool instance].downloadSession downloadTaskWithURL:[NSURL URLWithString:url]];
            downloadTask.taskDescription = @"downloadTask01";
            [downloadTask resume];
        }
    

      3.1 先建立一个downloadTask,用唯一的session来启动,传入具体的URL。

      3.2 taskDescription,可以用来描述下载任务,这个属性是可以修改的,与taskIdentifier不同,taskIdentifier是由系统返回是,一般用数字来标识,可用性不高,我们可以把对下载任务的描述,唯一标识符等,放在taskDescription里面,到后面代理方法里面,可以根据downloadTask.taskDescription将这个值取出来

      3.3 resume:启动下载;必须调用这个方法,才会启动下载,否则不会。当然还有其他的方法,比如暂停、取消。

      4.实现代理方法 

      4.1 下载完成

    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
        //建立一个文件夹
        BOOL isDirectory;
        NSString * folderPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingString:@"/script"];
        BOOL isExistFolderPath = [[NSFileManager defaultManager]fileExistsAtPath:folderPath isDirectory:&isDirectory];
        
        if (!isExistFolderPath) {
            BOOL createFile = [[NSFileManager defaultManager]createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:nil];
            
            if (createFile) {
                NSLog(@"创建文件成功");
            }else{
                NSLog(@"创建文件失败");
            }
        }
        
        //改变位置
        NSString * sourcePath = location.path;
        NSString * lastComponent = scScript.url.lastPathComponent;
        NSString * destinationPath = [folderPath stringByAppendingPathComponent:lastComponent];
        [[NSFileManager defaultManager]moveItemAtPath:sourcePath toPath:destinationPath error:nil];
        
        //保存到数据库
        [[DownloadStoreManager sharedInstance]insertScript:scScript];
        
        //发送消息
        NSDictionary * dic = @{@"script":scScript};
        [[NSNotificationCenter defaultCenter]postNotificationName:DownloadNotificationName object:nil userInfo:dic];
        NSLog(@"下载成功------");
    }
    

      这个是下载完成比较早的一个方法,后面还有一个方法。

      在这个方法里面,会将下载到的文件,暂时放置temp文件里面,如果我们不处理,系统稍后会把这个文件给清除掉,所以,在这个里面,我们的任务之一,就是把文件移动到目标文件夹里面去。如果目标文件不存在,我们要创建一个文件夹。后面,有可能要存入到数据库里面,这个依业务来定。最后发送消息:DownloadNotificationName是我定义的消息的名称,这个可以依具体情况而定。

      3.2 数据下载完成的第二个方法

    //下载完成
    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
    didCompleteWithError:(NSError *)error{
        
        if (error) {        
            NSDictionary * dic = @{@"error":@"下载失败"};
            [[NSNotificationCenter defaultCenter]postNotificationName:DownloadNotificationName object:nil userInfo:dic];
        }
        
    }
    

      一开始,我被这个方法名字给误导了,以为只有下载失败的时候才会调用这个方法,其实不是的,这个是在任务完成,不管是成功或者失败,都是要调用的一个方法。如果error为null,则说明下载成功,如果error有值,则下载失败,通过error这个值来判别。

    当前NSURLSession里面,还有很多其他的方法,比如下载Data、upload上传,原理差不多。

    今天先总结到这。昨天晚上太晚了,就没写总结,今天早上补上。

    最近来接触新事物时,脑袋刚开始时,总是蒙蒙的,看来得多接受新事物才能调节啊!

  • 相关阅读:
    小程序开发经验分享汇总
    VUE插件总结
    前端开发中一些好用的chrome插件总结
    Vue-meta
    element-ui Cascader 级联选择器 点击label选中
    盘点一些跨端框架
    vue 组件自定义v-model
    mac更新node,npm版本
    数组/对象数组去重
    基于vue和svg的树形UI
  • 原文地址:https://www.cnblogs.com/tanglimei/p/4756486.html
Copyright © 2011-2022 走看看