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];
真相:
情人节第二个礼物:
以前觉得很神奇的野,用心去试试,会觉得很简单,不是吗?