ios专题 - 异步下载加下载进度显示

【罗国强原创】

今天被刺激了,愤概地要写下这边博文。

说到http异步下载,首先要知道其中的关键类。

关键类是NSURLConnection  NSURLRequest NSMutableURLRequest

委托是 NSURLConnectionDownloadDelegate NSURLConnectionDataDelegate NSURLConnectionDelegate

首先,我们要实现最基本的下载功能。

LQAsynDownload.h

//
//  LQAsynDownload.h
//  lgTest
//
//  Created by yons on 14-2-14.
//  Copyright (c) 2014年 GQ. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface LQAsynDownload : NSObject<NSURLConnectionDataDelegate>

@property (strong) NSURL *httpURL;

+ (LQAsynDownload *) initWithURL:(NSURL *) url;

- (void) startAsyn;

@end

LQAsynDownload.m

//
//  LQAsynDownload.m
//  lgTest
//
//  Created by yons on 14-2-14.
//  Copyright (c) 2014年 GQ. All rights reserved.
//

#import "LQAsynDownload.h"

@interface LQAsynDownload()

@property (assign) long long contentLength;

@property (assign) long long receiveLength;

@property (strong) NSMutableData *receiveData;

@property (strong) NSString *fileName;

@property (strong) NSURLConnection *theConnection;

@property (strong) NSURLRequest *theRequest;

@end

@implementation LQAsynDownload

@synthesize receiveData = _receiveData, fileName = _fileName,
            theConnection=_theConnection, theRequest=_theRequest;

+ (LQAsynDownload *) initWithURL:(NSURL *) url{
    LQAsynDownload *asynDownload = [[LQAsynDownload alloc] init];
    asynDownload.theRequest=[NSURLRequest requestWithURL:url
              cachePolicy:NSURLRequestUseProtocolCachePolicy
                     timeoutInterval:60.0];
    // create the connection with the request
    // and start loading the data
    return asynDownload;
}

- (void) startAsyn{
    _contentLength=0;
    _receiveLength=0;
    self.receiveData = [[NSMutableData alloc] init];
    self.theConnection = [[NSURLConnection alloc] initWithRequest:self.theRequest delegate:self];
}

//接收到http响应
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    _contentLength = [response expectedContentLength];
    _fileName = [response suggestedFilename];
    NSLog(@"data length is %lli", _contentLength);
}

//传输数据
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    _receiveLength += data.length;
    [_receiveData appendData:data];
    NSLog(@"data recvive is %lli", _receiveLength);
}

//错误
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    [self releaseObjs];
    NSLog(@"%@",error.description);
}

- (void) releaseObjs{
    self.receiveData = nil;
    self.fileName = nil;
    self.theRequest = nil;
    self.theConnection = nil;
}

//成功下载完毕
- (void) connectionDidFinishLoading:(NSURLConnection *)connection{
    //数据写入doument
    //获取完整目录名字
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *savePath = [NSString stringWithFormat:@"%@/%@",documentsDirectory, _fileName];
    //创建文件
    [_receiveData writeToFile:savePath atomically:YES];
    [self releaseObjs];
}


@end

最简单的功能调用代码:

LQAsynDownload *dwn = [LQAsynDownload initWithURL:[[NSURL alloc] initWithString:@"http://t2.baidu.com/it/u=0,3067863433&fm=19&gp=0.jpg"]];
[dwn startAsyn];

查查模拟器,神啊,MM靓图出现了

情人节努力的补充礼物,哈哈。

 

 

关键点分析:

其实就是实现NSURLConnectionData委托的几个方法:

这个方法是客户端接收到回应后的调用方法,算是下载的开始。

- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

跟着就是接收数据的方法

-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

还有一个遇到错误时的处理方法

- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

最后是下载成功调用的方法

- (void) connectionDidFinishLoading:(NSURLConnection *)connection

 

接着实现,下载进度查看。

在原代码基础上增加2个block 属性。

LQAsynDownload.h

 1 //
 2 //  LQAsynDownload.h
 3 //  lgTest
 4 //
 5 //  Created by yons on 14-2-14.
 6 //  Copyright (c) 2014年 GQ. All rights reserved.
 7 //
 8 
 9 #import <Foundation/Foundation.h>
10 
11 typedef void (^initProgress)(long long initValue);
12 
13 typedef void (^loadedData)(long long loadedLength);
14 
15 @interface LQAsynDownload : NSObject<NSURLConnectionDataDelegate>
16 
17 @property (strong) NSURL *httpURL;
18 
19 @property (copy) void (^initProgress)(long long initValue);
20 
21 @property (copy) void (^loadedData)(long long loadedLength);
22 
23 + (LQAsynDownload *) initWithURL:(NSURL *) url;
24 
25 - (void) startAsyn;
26 
27 @end

LQAsynDownload.m

 1 //
 2 //  LQAsynDownload.m
 3 //  lgTest
 4 //
 5 //  Created by yons on 14-2-14.
 6 //  Copyright (c) 2014年 GQ. All rights reserved.
 7 //
 8 
 9 #import "LQAsynDownload.h"
10 
11 @interface LQAsynDownload()
12 
13 @property (assign) long long contentLength;
14 
15 @property (assign) long long receiveLength;
16 
17 @property (strong) NSMutableData *receiveData;
18 
19 @property (strong) NSString *fileName;
20 
21 @property (strong) NSURLConnection *theConnection;
22 
23 @property (strong) NSURLRequest *theRequest;
24 
25 @end
26 
27 @implementation LQAsynDownload
28 
29 @synthesize receiveData = _receiveData, fileName = _fileName,
30             theConnection=_theConnection, theRequest=_theRequest;
31 
32 + (LQAsynDownload *) initWithURL:(NSURL *) url{
33     LQAsynDownload *asynDownload = [[LQAsynDownload alloc] init];
34     asynDownload.theRequest=[NSURLRequest requestWithURL:url
35               cachePolicy:NSURLRequestUseProtocolCachePolicy
36                      timeoutInterval:60.0];
37     // create the connection with the request
38     // and start loading the data
39     return asynDownload;
40 }
41 
42 - (void) startAsyn{
43     _contentLength=0;
44     _receiveLength=0;
45     self.receiveData = [[NSMutableData alloc] init];
46     self.theConnection = [[NSURLConnection alloc] initWithRequest:self.theRequest delegate:self];
47 }
48 
49 //接收到http响应
50 - (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
51     _contentLength = [response expectedContentLength];
52     _fileName = [response suggestedFilename];
53     if (self.initProgress != nil) {
54         self.initProgress(_contentLength);
55     }
56     NSLog(@"data length is %lli", _contentLength);
57 }
58 
59 //传输数据
60 -(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
61     _receiveLength += data.length;
62     [_receiveData appendData:data];
63     if (self.loadedData != nil) {
64         self.loadedData(data.length);
65     }
66     NSLog(@"data recvive is %lli", _receiveLength);
67 }
68 
69 //错误
70 - (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
71     [self releaseObjs];
72     NSLog(@"%@",error.description);
73 }
74 
75 - (void) releaseObjs{
76     self.receiveData = nil;
77     self.fileName = nil;
78     self.theRequest = nil;
79     self.theConnection = nil;
80 }
81 
82 //成功下载完毕
83 - (void) connectionDidFinishLoading:(NSURLConnection *)connection{
84     //数据写入doument
85     //获取完整目录名字
86     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
87     NSString *documentsDirectory = [paths objectAtIndex:0];
88     NSString *savePath = [NSString stringWithFormat:@"%@/%@",documentsDirectory, _fileName];
89     //创建文件
90     [_receiveData writeToFile:savePath atomically:YES];
91     [self releaseObjs];
92 }
93 
94 
95 @end

调用代码:

 1 LQAsynDownload *dwn = [LQAsynDownload initWithURL:[[NSURL alloc] initWithString:@"http://a.hiphotos.baidu.com/image/w%3D2048/sign=fae75ab5d63f8794d3ff4f2ee6230ff4/faedab64034f78f09f9423fe7b310a55b3191c1b.jpg"]];
 2     
 3     dwn.initProgress = ^(long long initValue){
 4         _sum = initValue;
 5         NSLog(@"%lli",initValue);
 6         _rcv = 0;
 7         dispatch_async(dispatch_get_main_queue(), ^{
 8             self.pv.progress = 0.0;
 9             self.pv.hidden = NO;
10         });
11     };
12     
13     dwn.loadedData = ^(long long loadedLength){
14         dispatch_async(dispatch_get_main_queue(), ^{
15             if (_rcv == _sum) {
16                 self.pv.hidden = YES;
17             } else {
18                 _rcv += loadedLength;
19                 self.pv.progress = _rcv/_sum;
20             }
21         });
22     };
23     
24     [dwn startAsyn];

真相:

情人节第二个礼物:

以前觉得很神奇的野,用心去试试,会觉得很简单,不是吗?

 

 

 

posted @ 2014-02-14 22:30  路途遥远  阅读(11083)  评论(5编辑  收藏  举报