IOS网络通信
之ASIHttpRequest的使用(三)
本文将介绍一下ASIHttpRequest的进度追踪.
每个ASI都有两个delegate来追踪进度,分别是追踪上传进度的uploadProgressDelegate和追踪下载进度的downloadProgressDelegate.这两个代理方法可以是NSProgressIndicators(Mac OS X)或者 UIProgressViews (iPhone).ASIHTTPRequest会自适应这两个class的行为。
先分析下载进度的追踪:
(1) 追踪单个请求的下载进度
这个demo中的 self.progressView是UIProgressViews
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:urlStr]; //定义下载路径 NSString *downloadPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/123.jpg"]; request.downloadDestinationPath = downloadPath; //设置下载进度的追踪代理 [request setDownloadProgressDelegate:self.progressView]; //设置下载完成后回掉的block [request setCompletionBlock:^{ [sender setTitle:@"下载" forState:UIControlStateNormal]; sender.enabled = YES; self.progressLabel.text = @"下载完成"; }]; //发送异步请求 [request startAsynchronous];
(2) 追踪ASINetworkQueue中的请求的下载进度
- (void)progess:(NSURL *)url { myQueue = [[ASINetworkQueue alloc]init]; [myQueue setDownloadProgressDelegate:self.progressView]; [myQueue setDelegate:self]; [myQueue setRequestDidFinishSelector:@selector(finished:)]; [myQueue setMaxConcurrentOperationCount:5]; for (int i = 0; i < 5; i++) { ASIHTTPRequest *request= [ASIHTTPRequest requestWithURL:url]; [myQueue addOperation:request]; } [myQueue go]; }
(3) 追中单个请求的上传进度
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:urlStr]]; //设置数据请求方式为POST [request setRequestMethod:@"POST"]; //添加表单数据 [request setValue:@"jack" forKey:@"name"]; [request setValue:@22 forKey:@"age"]; [request setUploadProgressDelegate:self.progressView]; [request startSynchronous];
(4) 追中队列中请求的上传进度与下载进度相似只要该一句代码
[myQueue setUploadProgressDelegate:self.progressView];
但要注意这里添加表单数据的时候,会存在OC字符串转码转化为字符串的问题.
如: [requestsetPostBody:[@"Some data"dataUsingEncoding:NSUTF8StringEncoding]];
学会了请求的进度追踪下一步就要想办法把追踪到的进度可视化的显示出来,ASI也为我们提供了一个方法showAccurateProgress来显示进度条.注意为一个request设置showAccurateProgress只会对该request有效。如果你为一个队列设置showAccurateProgress,那么会影响队列里所有的request。
ASI提供了两种进度条,简单进度条和精度进度条.
简单进度条
当使用简单进度条时,进度条只会在一个request完成时才更新。对于单个request,这意味着你只有两个进度状态:0%和100%。对于一个有5个request的队列来说,有五个状态:0%,25%,50%,75%,100%,每个request完成时,进度条增长一次。
简单进度条(showAccurateProgress = NO)是ASINetworkQueue的默认值,适用于大量小数据请求。
精确进度条
当使用精确进度条时,每当字节被上传或下载时,进度条都会更新。它适用于上传/下载大块数据的请求,并且会更好的显示已经发送/接收的数据量。
使用精确进度条追踪上传会轻微降低界面效率,因为进度delegate(一般是UIProgressViews或NSProgressIndicators)会更频繁地重绘。
使用精确进度条追踪下载会更影响界面效率,因为队列会先为每个GET型request进行HEAD请求,以便统计总下载量。强烈推荐对下载大文件的队列使用精确进度条,但是要避免对大量小数据请求使用精确进度条。
精确进度条(showAccurateProgress = YES)是以同步方式执行的ASIHTTPRequest的默认值。
下面是一个显示精确进度条的demo:
- (IBAction)download:(UIButton *)sender { NSURL *url = [NSURL URLWithString:@"http://pic1.win4000.com/pic/4/3f/4124407336.jpg"]; ASIHTTPRequest *request= [ASIHTTPRequest requestWithURL:url]; [request setDelegate:self]; [request setDownloadProgressDelegate:self.progressView]; //开启精确进度条 [request setShowAccurateProgress:YES]; [request startSynchronous]; }
可以在进度条旁边拖一个label来显示进度的百分比,核心代码如下:
//计算百分比 //注意在block中要用到的变量receiveSize需要用__block修饰 __block long long receiveSize = 0; //request接收到数据(字节)时回调的block [request setBytesReceivedBlock:^(unsigned long long size, unsigned long long total) { receiveSize += size; float progress = (float)receiveSize/total * 100; self.progressLabel.text = [NSString stringWithFormat:@"%.1f%%",progress];//显示百分比 }];
或者更简单一点添加观察者,用KVO实现
//KVO计算下载进度label的显示值 [_progressView addObserver:self forKeyPath:@"progress" options:NSKeyValueObservingOptionNew context:nil]; //观察对象的被观察属性值改变时调用下面的方法 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { id value = [change objectForKey:@"new"]; float mValue = [value floatValue]; self.progressLabel.text = [NSString stringWithFormat:@"%.1f%%",mValue*100]; }