iPhone开发【十七】多线程开发之NSOperation&NSOperationQueue——异步下载图片

来源:互联网 发布:nginx tomcat 502错误 编辑:程序博客网 时间:2024/06/05 00:44

转载请注明出处,原文网址:http://blog.csdn.net/m_changgong/article/details/8238093 作者:张燕广

实现的功能:1)演示多线程NSOperation&NSOperationQueue开发;2)子线程中执行下载图片工作,图片下载完成前显示等待框和下载进度条;

关键词:多线程 NSOperation NSOperationQueue 等待框

1、新建视图控制器ViewController(不带xib),作为根视图控制器,通过ViewController的-(void)loadView方法构建UI。

2、新建继承自NSOperation且实现协议NSURLConnectionDelegate的类DownLoadImageTask,DownLoadImageTask.h如下:

[cpp] view plaincopy
  1. #import <Foundation/Foundation.h>  
  2. @protocol DownLoadImageDelegate;  
  3.   
  4. @interface DownLoadImageTask : NSOperation<NSURLConnectionDelegate>{  
  5.     int operationId;  
  6.     long long totalLength;  
  7.     BOOL done;  
  8. }  
  9. @property int operationId;  
  10. @property(nonatomic,assign) id<DownLoadImageDelegate>downloadImageDelegate;  
  11. @property(nonatomic,retain) NSMutableData *buffer;  
  12. @property(nonatomic,retain) NSURLRequest *request;  
  13. @property(nonatomic,retain) NSURLConnection *connection;  
  14.   
  15. - (id)initWithURLString:(NSString *)url;  
  16. @end  
  17.   
  18.   
  19. @protocol DownLoadImageDelegate  
  20. //图片下载完成的委托  
  21. -(void)imageDownLoadFinished:(UIImage *)img;  
  22. //更新图片下载进度条的值  
  23. -(void)updateDownProgress:(double) value;  
  24. @end  
DownLoadImageTask.m如下:

[cpp] view plaincopy
  1. <span style="font-family:Microsoft YaHei;font-size:18px;">#import "DownLoadImageTask.h"  
  2.   
  3. @implementation DownLoadImageTask  
  4. @synthesize operationId;  
  5. @synthesize downloadImageDelegate;  
  6. @synthesize buffer;  
  7. @synthesize request;  
  8. @synthesize connection;  
  9.   
  10. - (id)initWithURLString:(NSString *)url{  
  11.     NSLog(@"url=%@",url);  
  12.     self = [super init];  
  13.     if(self){  
  14.         request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];  
  15.         buffer = [NSMutableData data];  
  16.     }  
  17.     return self;  
  18. }  
  19.   
  20. //主要处理方法  
  21. -(void)start{ //或者main  
  22.     NSLog(@"DownLoadImageTask-start");  
  23.       
  24.     if(![self isCancelled]){  
  25.         //暂停一下  
  26.         [NSThread sleepForTimeInterval:1];  
  27.         //设置connection及其代理  
  28.         connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];  
  29.         if(connection!=nil){  
  30.             while(!done){  
  31.                 [[NSRunLoop currentRunLoop]runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];  
  32.             }  
  33.         }  
  34.     }  
  35. }  
  36.   
  37. -(void)httpConnectEndWithError{  
  38.     //[self hiddenWaiting];  
  39.     NSLog(@"httpConnectEndWithError");  
  40. }  
  41.   
  42. -(void)dealloc{  
  43.     buffer = nil;  
  44.     connection = nil;  
  45.     request = nil;  
  46.     downloadImageDelegate = nil;  
  47. }  
  48.   
  49. #pragma NSURLConnection delegate methods  
  50. //不执行缓存  
  51. -(NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse{  
  52.     return nil;  
  53. }  
  54.   
  55. //连接发生错误  
  56. -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{  
  57.     [self performSelectorOnMainThread:@selector(httpConnectEndWithError) withObject:self waitUntilDone:NO];  
  58.     [buffer setLength:0];  
  59. }  
  60.   
  61. //收到响应  
  62. - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{  
  63.     NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;  
  64.     if(httpResponse && [httpResponse respondsToSelector:@selector(allHeaderFields)]){  
  65.         NSDictionary *httpResponseHeaderFields = [httpResponse allHeaderFields];  
  66.         totalLength = [[httpResponseHeaderFields objectForKey:@"Content-Length"] longLongValue];  
  67.         NSLog(@"totalLength is %lld",totalLength);  
  68.     }  
  69. }  
  70.   
  71. //接收数据  
  72. -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{  
  73.     //NSLog(@"didReceiveData...");  
  74.     [buffer appendData:data];  
  75.       
  76.     double progressValue = totalLength==0?0:((double)([buffer length])/(double)totalLength);  
  77.     //更新进度条值  
  78.     [downloadImageDelegate updateDownProgress:progressValue];  
  79. }  
  80.   
  81. //下载完毕  
  82. -(void)connectionDidFinishLoading:(NSURLConnection *)connection{  
  83.     done = YES;  
  84.     UIImage *img = [[UIImage alloc] initWithData:buffer];  
  85.     [downloadImageDelegate imageDownLoadFinished:img];  
  86. }  
  87.   
  88. -(BOOL)isConcurrent {  
  89.     //返回yes表示支持异步调用,否则为支持同步调用  
  90.     return YES;  
  91.       
  92. }  
  93.   
  94. - (BOOL)isExecuting{  
  95.     return connection == nil;   
  96. }  
  97.   
  98. - (BOOL)isFinished{  
  99.     return connection == nil;    
  100. }  
  101.   
  102. @end</span>  
DownLoadImageTask中定义了协议DownLoadImageDelegate,ViewController需要实现协议DownLoadImageDelegate;DownLoadImageTask下载工作完成后,会回调ViewController实现的DownLoadImageDelegate协议中的方法。

2、ViewController.h如下:

[cpp] view plaincopy
  1. <span style="font-family:Microsoft YaHei;font-size:18px;">#import <UIKit/UIKit.h>  
  2. #import "DownLoadImageTask.h"  
  3.   
  4. @interface ViewController:UIViewController<DownLoadImageDelegate>{  
  5. }  
  6.   
  7. @property(strong,nonatomic)NSOperationQueue *queue;  
  8. @property(strong,nonatomic)UIImageView *appImgView;  
  9.   
  10. @end</span>  

ViewController.m如下:

[cpp] view plaincopy
  1. <span style="font-family:Microsoft YaHei;font-size:18px;">#import "ViewController.h"  
  2. #import "DownLoadImageTask.h"  
  3.   
  4. @implementation ViewController  
  5. @synthesize queue;  
  6. @synthesize appImgView;  
  7.   
  8. -(void)loadView{  
  9.     //初始化视图  
  10.     [self initViews];  
  11.       
  12.     //显示等待框  
  13.     [self showWaiting];  
  14.     NSString *url = @"http://hiphotos.baidu.com/newwen666666/pic/item/01ec7750863e49600cf3e3cc.jpg";  
  15.     int index = 1;  
  16.       
  17.     DownLoadImageTask *task = [[DownLoadImageTask alloc]initWithURLString:url];  
  18.     task.downloadImageDelegate = self;  
  19.     task.operationId = index++;  
  20.       
  21.     queue = [[NSOperationQueue alloc]init];  
  22.     [queue addOperation:task];  
  23. }  
  24.   
  25. //初始化视图组件  
  26. -(void)initViews{  
  27.     CGRect frame = [UIScreen mainScreen].applicationFrame;  
  28.     UIView *appView = [[UIView alloc]initWithFrame:frame];  
  29.     self.view = appView;  
  30.     [self.view setBackgroundColor:[UIColor colorWithWhite:1.0 alpha:1.0]];  
  31.       
  32.     frame = CGRectMake(0, 0, frame.size.width, frame.size.height);  
  33.     appImgView = [[UIImageView alloc]initWithFrame:frame];  
  34.       
  35.     [self.view addSubview:appImgView];  
  36. }  
  37.   
  38. //展示等待框  
  39. -(void)showWaiting{  
  40.     CGRect frame = CGRectMake(0, -20, 320, 480);  
  41.     int x = frame.size.width;  
  42.     
  43.     int progressWidth = 150;  
  44.     int progressHeight = 32;  
  45.     frame = CGRectMake((x-progressWidth)/2, 100, progressWidth, progressHeight);  
  46.     UIProgressView *progress = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];  
  47.     progress.frame = frame;  
  48.     progress.progress = 0.0;  
  49.     progress.backgroundColor = [UIColor whiteColor];  
  50.       
  51.     UILabel *showValue = [[UILabel alloc]init];    
  52.     frame = showValue.frame;    
  53.     frame.origin.x = CGRectGetMaxX(progress.frame)+10;    
  54.     frame.origin.y = CGRectGetMinY(progress.frame);    
  55.     frame.size.width = 45;    
  56.     frame.size.height = 15;    
  57.     showValue.frame = frame;    
  58.     showValue.backgroundColor = [UIColor redColor];    
  59.     showValue.text = @"0.0";    
  60.       
  61.       
  62.     int progressIndWidth = 32;  
  63.     int progressIndHeight = 32;  
  64.     frame = CGRectMake((x-progressIndWidth)/2, 100+32, progressIndWidth, progressIndHeight);  
  65.     UIActivityIndicatorView *progressInd = [[UIActivityIndicatorView alloc]initWithFrame:frame];  
  66.     [progressInd startAnimating];  
  67.     progressInd.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;  
  68.       
  69.     frame = CGRectMake((x-70)/2, 100+32+32, 80, 20);  
  70.     UILabel *waitinglabel = [[UILabel alloc]initWithFrame:frame];  
  71.     waitinglabel.text = @"正在下载应用程序图片...";  
  72.     waitinglabel.textColor = [UIColor redColor];  
  73.     waitinglabel.font = [UIFont systemFontOfSize:15];  
  74.     waitinglabel.backgroundColor = [UIColor clearColor];  
  75.       
  76.     frame = CGRectMake(0, -20, 320, 480);  
  77.     UIView *theView = [[UIView alloc]initWithFrame:frame];  
  78.     theView.backgroundColor = [UIColor blackColor];  
  79.     theView.alpha = 0.7;  
  80.       
  81.     [progress setTag:100];  
  82.     [theView addSubview:progress];  
  83.     [showValue setTag:101];  
  84.     [theView addSubview:showValue];  
  85.       
  86.     [theView addSubview:progressInd];  
  87.     [theView addSubview:waitinglabel];  
  88.       
  89.     [theView setTag:110];  
  90.     [self.view addSubview:theView];  
  91. }  
  92.   
  93. //隐藏等待框  
  94. -(void)hiddenWaiting{  
  95.     [[self.view viewWithTag:110]removeFromSuperview];  
  96. }  
  97.   
  98. - (void)viewDidUnload  
  99. {  
  100.     [super viewDidUnload];  
  101.     // Release any retained subviews of the main view.  
  102. }  
  103.   
  104. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation  
  105. {  
  106.     return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);  
  107. }  
  108.   
  109. #pragma mark DownLoadImageDelegate methods  
  110. //展示下载完毕的图片  
  111. -(void)imageDownLoadFinished:(UIImage *)img{  
  112.     //退出等待框  
  113.     [self hiddenWaiting];  
  114.     [appImgView setImage:img];  
  115. }  
  116.   
  117. //更新进度条的值  
  118. -(void)updateDownProgress:(double) value{  
  119.     UIProgressView *progresss = (UIProgressView *)[self.view viewWithTag:100];  
  120.     UILabel *showValue = (UILabel*)[self.view viewWithTag:101];  
  121.     progresss.progress = value;  
  122.     showValue.text = [NSString stringWithFormat:@"%.1f%",(double)(value*100)];  
  123. }  
  124.   
  125. @end</span>  

3、效果如下:



0 0
原创粉丝点击