您的位置:首页 > 移动开发 > IOS开发

iOS开发 -文件下载(下载功能的封装)

2016-07-26 23:42 441 查看
一、简单说明

在前面几篇文章介绍下载代码的基础上,此文分析对下载功能进行封装。

通过之前的代码,我们发现仅仅是下载一个文件就需要写很长的代码,那么如果要下载多个文件,就需要写多份代码。在这里,我们把下载一个文件的代码进行封装。控制器只需要知道,下载哪个文件,下载到哪个路径就可以了。

在对下载的功能进行封装后,添加一个文件下载器,一个文件下载器只下载一个文件,封装后如果要下载多个文件的话,那么只需要创建多个文件下载器对象就可以进行控制和下载了。

 

二、代码示例

1.代码:

新建一个类,让其继承自NSObject类,一个文件下载器只下载一个文件。

自定义类的头文件代码:





1 //
2 //  YYfileDownloader.h
3 //
4 //
5 //  Created by apple on 14-7-1.
6 //  Copyright (c) 2014年 itcase. All rights reserved.
7 //
8
9 #import
10
11 @interface YYfileDownloader : NSObject
12 //下载的远程url(连接到服务器的路径)
13 @property(nonatomic,strong)NSString *url;
14 //下载后的存储路径(文件下载到什么地方)
15 @property(nonatomic,strong)NSString *destPath;
16 //是否正在下载(只有下载器内部清楚)
17 @property(nonatomic,readonly,getter = isDownloading)BOOL Downloading;
18 //用来监听下载进度
19 @property(nonatomic,copy)void (^progressHandler)(double progress);
20 //用来监听下载完成
21 @property(nonatomic,copy)void (^completionHandler)();
22 //用来监听下载错误
23 @property(nonatomic,copy)void(^failureHandler)(NSError *error);
24 -(void)pause;
25 -(void)start;
26 @end






自定义类的实现代码:





1 //
2 //  YYfileDownloader.m
3 //  4 //
5 //  Created by apple on 14-7-1.
6 //  Copyright (c) 2014年 itcase. All rights reserved.
7 //
8
9 #import "YYfileDownloader.h"
10
11 @interface YYfileDownloader ()
12 //请求对象
13 @property(nonatomic,strong)NSURLConnection *cnnt;
14 //文件句柄
15 @property(nonatomic,strong)NSFileHandle *writeHandle;
16 //当前获取到的数据长度
17 @property(nonatomic,assign)long long currentLength;
18 //完整数据长度
19 @property(nonatomic,assign)long long sumLength;
20
21 @end
22 @implementation YYfileDownloader
23 //开始下载
24 -(void)start
25 {
26         _Downloading=YES;
27
28     //创建一个请求
29     NSURL *URL=[NSURL URLWithString:self.url];
30     NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:URL];
31
32     //设置请求头信息
33     //self.currentLength字节部分重新开始读取
34     NSString *value=[NSString stringWithFormat:@"bytes=%lld-",self.currentLength];
35     [request setValue:value forHTTPHeaderField:@"Range"];
36
37     //发送请求(使用代理的方式)
38     self.cnnt=[NSURLConnection connectionWithRequest:request delegate:self];
39
40 }
41
42 //暂停下载
43 -(void)pause
44 {
45     _Downloading=NO;
46     //取消发送请求
47     [self.cnnt cancel];
48     self.cnnt=nil;
49 }
50
51 #pragma mark- NSURLConnectionDataDelegate代理方法
52
55 -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
56 {
57 #warning 判断是否是第一次连接
58     if (self.sumLength) return;
59
60     //1.创建文件存数路径
61     NSString *caches=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
62     NSString *filePath=[caches stringByAppendingPathComponent:@"video.zip"];
63
64
65
66     //2.创建一个空的文件,到沙盒中
67     NSFileManager *mgr=[NSFileManager defaultManager];
68     //刚创建完毕的大小是o字节
69     [mgr createFileAtPath:filePath contents:nil attributes:nil];
70
71     //3.创建写数据的文件句柄
72     self.writeHandle=[NSFileHandle fileHandleForWritingAtPath:filePath];
73
74     //4.获取完整的文件长度
75     self.sumLength=response.expectedContentLength;
76 }
77
78
81 -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
82 {
83     //累加接收到的数据长度
84     self.currentLength+=data.length;
85     //计算进度值
86     double progress=(double)self.currentLength/self.sumLength;
87 //    self.progress.progress=progress;
88     if (self.progressHandler) {//传递进度值给block
89         self.progressHandler(progress);
90
91         //相当于在此处调用了下面的代码
92 //        ^(double progress)
93 //        {
94 //            //把进度的值,传递到控制器中进度条,以进行显示
95 //            vc.progress.progress=progress;
96 //        };
97     }
98
99
100     //一点一点接收数据。
101     NSLog(@"接收到服务器的数据!---%d",data.length);
102     //把data写入到创建的空文件中,但是不能使用writeTofile(会覆盖)
103     //移动到文件的尾部
104     [self.writeHandle seekToEndOfFile];
105     //从当前移动的位置,写入数据
106     [self.writeHandle writeData:data];
107 }
108
109
112 -(void)connectionDidFinishLoading:(NSURLConnection *)connection
113 {
114     NSLog(@"下载完毕----%lld",self.sumLength);
115     //关闭连接,不再输入数据在文件中
116     [self.writeHandle closeFile];
117     self.writeHandle=nil;
118
119     //清空进度值
120     self.currentLength=0;
121     self.sumLength=0;
122
123     if (self.completionHandler) {//下载完成通知控制器
124         self.completionHandler();
125         //相当于下面的代码
126 //        ^{
127 //            NSLog(@"下载完成");
128 //            [self.btn setTitle:@"下载已经完成" forState:UIControlStateNormal];
129 //        }
130     }
131
132 }
133
136 -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
137 {
138     if (self.failureHandler) {//通知控制器,下载出错
139         self.failureHandler(error);
140     //相当于调用了下面的代码
141 //        ^{
142 //            NSLog(@"下载错误!");
143 //        }
144     }
145 }
146
147 @end






主控制器代码:





1 //
2 //  YYViewController.m
3 //  01-文件的下载(不合理)
4 //
5 //  Created by apple on 14-6-30.
6 //  Copyright (c) 2014年 itcase. All rights reserved.
7 //
8
9 #import "YYViewController.h"
10 #import "YYfileDownloader.h"
11
12 @interface YYViewController ()
13
14 @property(nonatomic,strong)YYfileDownloader *fileDownloader;
15 @property (weak, nonatomic) IBOutlet UIButton *btn;
16 @property (weak, nonatomic) IBOutlet UIProgressView *progress;
17 @end
18
19 @implementation YYViewController
20
21 - (void)viewDidLoad
22 {
23     [super viewDidLoad];
24 }
25
26 #pragma mark-懒加载
27 -(YYfileDownloader *)fileDownloader
28 {
29     if (_fileDownloader==nil) {
30         _fileDownloader=[[YYfileDownloader alloc]init];
31         //设置文件下载路径
32         _fileDownloader.url=@"http://192.168.1.53:8080/MJServer/resources/video.zip";
33
34         //设置文件保存路径
35         NSString *caches=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
36         NSString *filePath=[caches stringByAppendingPathComponent:@"video.zip"];
37         _fileDownloader.destPath=filePath;
38
39         //获取10的真实类型,把它作为a的类型
40 //        typeof(10) a = 20; // int a = 20;
41         __weak typeof(self) vc=self;
42         _fileDownloader.progressHandler=^(double progress)
43         {
44             vc.progress.progress=progress;
45             NSLog(@"%f",progress);
46         };
47         _fileDownloader.completionHandler=^{
48             NSLog(@"下载完成");
49             [vc.btn setTitle:@"下载已经完成" forState:UIControlStateNormal];
50         };
51         _fileDownloader.failureHandler=^(NSError *error){
52             NSLog(@"下载错误!%@",error);
53         };
54     }
55     return _fileDownloader;
56 }
57
58 //点击下载按钮,处理操作
59 - (IBAction)star {
60     if (self.fileDownloader.isDownloading) {//如果正在下载,那么调用方法暂停
61         [self.fileDownloader pause];
62         [self.btn setTitle:@"暂停" forState:UIControlStateNormal];
63     }else//如果没有正在下载,那么调用下载方法
64     {
65         [self.fileDownloader start];
66         [self.btn setTitle:@"下载" forState:UIControlStateNormal];
67     }
68   }
69
70 @end






2.代码说明

要在控制器中拿到下载的进度,可以使用代理,也可以使用block,这里使用block来进行实现。

给下载器传递一个下载进度的block,每隔一段时间,下载器就调用一次该block,然后把进度信息传递给外部的进度条进行显示。





-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
//累加接收到的数据长度
self.currentLength+=data.length;
//计算进度值
double progress=(double)self.currentLength/self.sumLength;
//    self.progress.progress=progress;
if (self.progressHandler) {//传递进度值给block
self.progressHandler(progress);

//相当于在此处调用了下面的代码
//        ^(double progress)
//        {
//            //把进度的值,传递到控制器中进度条,以进行显示
//            vc.progress.progress=progress;
//        };
}






在控制器中对进度值进行监听:

_fileDownloader.progressHandler=^(double progress)
{
vc.progress.progress=progress;
NSLog(@"%f",progress);
};


控制器想监听下载器的下载进度,控制器想监听下载器的下载完毕,控制器想监听下载器的下载失败等都可以使用block的方式进行。

打印查看:



三、补充

在IOS开发中,有的时候我们需要在已经存在的旧项目基础上,进行改进,下面说明怎么更改项目及文件的名称。

(1)打开项目后,点击修改项目的名称。



(2)修改完之后,点击回车,弹出下面的窗口。



(3)在导航栏上,如图点击。



(4)修改名称,之后点击OK。



(5)修改剩下的两个文件的名称。



至此,已经完成了所有的修改。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: