现在的位置: 首页 > 综合 > 正文

多线程开发之NSOperation&NSOperationQueue——异步下载图片

2014年09月24日 ⁄ 综合 ⁄ 共 6884字 ⁄ 字号 评论关闭

原文网址: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如下:

#import <Foundation/Foundation.h>  
@protocol DownLoadImageDelegate;  
  
@interface DownLoadImageTask : NSOperation<NSURLConnectionDelegate>{  
    int operationId;  
    long long totalLength;  
    BOOL done;  
}  
@property int operationId;  
@property(nonatomic,assign) id<DownLoadImageDelegate>downloadImageDelegate;  
@property(nonatomic,retain) NSMutableData *buffer;  
@property(nonatomic,retain) NSURLRequest *request;  
@property(nonatomic,retain) NSURLConnection *connection;  
  
- (id)initWithURLString:(NSString *)url;  
@end  
  
  
@protocol DownLoadImageDelegate  
//图片下载完成的委托  
-(void)imageDownLoadFinished:(UIImage *)img;  
//更新图片下载进度条的值  
-(void)updateDownProgress:(double) value;  
@end  

DownLoadImageTask.m如下:

#import "DownLoadImageTask.h"  
  
@implementation DownLoadImageTask  
@synthesize operationId;  
@synthesize downloadImageDelegate;  
@synthesize buffer;  
@synthesize request;  
@synthesize connection;  
  
- (id)initWithURLString:(NSString *)url{  
    NSLog(@"url=%@",url);  
    self = [super init];  
    if(self){  
        request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];  
        buffer = [NSMutableData data];  
    }  
    return self;  
}  
  
//主要处理方法  
-(void)start{ //或者main  
    NSLog(@"DownLoadImageTask-start");  
      
    if(![self isCancelled]){  
//暂停一下  
        [NSThread sleepForTimeInterval:1];  
        //设置connection及其代理  
        connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];  
        if(connection!=nil){  
            while(!done){  
                [[NSRunLoop currentRunLoop]runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];  
            }  
        }  
    }  
}  
  
-(void)httpConnectEndWithError{  
    //[self hiddenWaiting];  
    NSLog(@"httpConnectEndWithError");  
}  
  
-(void)dealloc{  
    buffer = nil;  
    connection = nil;  
    request = nil;  
    downloadImageDelegate = nil;  
}  
  
#pragma NSURLConnection delegate methods  
//不执行缓存  
-(NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse{  
    return nil;  
}  
  
//连接发生错误  
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{  
    [self performSelectorOnMainThread:@selector(httpConnectEndWithError) withObject:self waitUntilDone:NO];  
    [buffer setLength:0];  
}  
  
//收到响应  
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{  
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;  
    if(httpResponse && [httpResponse respondsToSelector:@selector(allHeaderFields)]){  
        NSDictionary *httpResponseHeaderFields = [httpResponse allHeaderFields];  
        totalLength = [[httpResponseHeaderFields objectForKey:@"Content-Length"] longLongValue];  
        NSLog(@"totalLength is %lld",totalLength);  
    }  
}  
  
//接收数据  
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{  
    //NSLog(@"didReceiveData...");  
    [buffer appendData:data];  
      
    double progressValue = totalLength==0?0:((double)([buffer length])/(double)totalLength);  
    //更新进度条值  
    [downloadImageDelegate updateDownProgress:progressValue];  
}  
  //下载完毕  
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{  
    done = YES;  
    UIImage *img = [[UIImage alloc] initWithData:buffer];  
    [downloadImageDelegate imageDownLoadFinished:img];  
}  
  
-(BOOL)isConcurrent {  
    //返回yes表示支持异步调用,否则为支持同步调用  
    return YES;  
      
}  
  
- (BOOL)isExecuting{  
    return connection == nil;   
}  
  
- (BOOL)isFinished{  
    return connection == nil;    
}  
  
@end

DownLoadImageTask中定义了协议DownLoadImageDelegate,ViewController需要实现协议DownLoadImageDelegate;DownLoadImageTask下载工作完成后,会回调ViewController实现的DownLoadImageDelegate协议中的方法。

2、ViewController.h如下:

#import <UIKit/UIKit.h>  
#import "DownLoadImageTask.h"  
  
@interface ViewController:UIViewController<DownLoadImageDelegate>{  
}  
  
@property(strong,nonatomic)NSOperationQueue *queue;  
@property(strong,nonatomic)UIImageView *appImgView;  
  
@end

ViewController.m如下:

#import "ViewController.h"  
#import "DownLoadImageTask.h"  
  
@implementation ViewController  
@synthesize queue;  
@synthesize appImgView;  
  
-(void)loadView{  
    //初始化视图  
    [self initViews];  
      
    //显示等待框  
    [self showWaiting];  
    NSString *url = @"http://hiphotos.baidu.com/newwen666666/pic/item/01ec7750863e49600cf3e3cc.jpg";  
    int index = 1;  
      
    DownLoadImageTask *task = [[DownLoadImageTask alloc]initWithURLString:url];  
    task.downloadImageDelegate = self;  
    task.operationId = index++;  
      
    queue = [[NSOperationQueue alloc]init];  
    [queue addOperation:task];  
}  
  
//初始化视图组件  
-(void)initViews{  
    CGRect frame = [UIScreen mainScreen].applicationFrame;  
    UIView *appView = [[UIView alloc]initWithFrame:frame];  
    self.view = appView;  
    [self.view setBackgroundColor:[UIColor colorWithWhite:1.0 alpha:1.0]];  
      
    frame = CGRectMake(0, 0, frame.size.width, frame.size.height);  
    appImgView = [[UIImageView alloc]initWithFrame:frame];  
[self.view addSubview:appImgView];  
}  
  
//展示等待框  
-(void)showWaiting{  
    CGRect frame = CGRectMake(0, -20, 320, 480);  
    int x = frame.size.width;  
    
    int progressWidth = 150;  
    int progressHeight = 32;  
    frame = CGRectMake((x-progressWidth)/2, 100, progressWidth, progressHeight);  
    UIProgressView *progress = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];  
    progress.frame = frame;  
    progress.progress = 0.0;  
    progress.backgroundColor = [UIColor whiteColor];  
      
    UILabel *showValue = [[UILabel alloc]init];    
    frame = showValue.frame;    
    frame.origin.x = CGRectGetMaxX(progress.frame)+10;    
 frame.origin.y = CGRectGetMinY(progress.frame);    
    frame.size.width = 45;    
    frame.size.height = 15;    
    showValue.frame = frame;    
    showValue.backgroundColor = [UIColor redColor];    
    showValue.text = @"0.0";    
      
      
    int progressIndWidth = 32;  
    int progressIndHeight = 32;  
    frame = CGRectMake((x-progressIndWidth)/2, 100+32, progressIndWidth, progressIndHeight);  
    UIActivityIndicatorView *progressInd = [[UIActivityIndicatorView alloc]initWithFrame:frame];  
    [progressInd startAnimating];  
    progressInd.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;  
      
    frame = CGRectMake((x-70)/2, 100+32+32, 80, 20);  
    UILabel *waitinglabel = [[UILabel alloc]initWithFrame:frame];  
    waitinglabel.text = @"正在下载应用程序图片...";  
    waitinglabel.textColor = [UIColor redColor];  
    waitinglabel.font = [UIFont systemFontOfSize:15];  
    waitinglabel.backgroundColor = [UIColor clearColor];  
      
    frame = CGRectMake(0, -20, 320, 480);  
    UIView *theView = [[UIView alloc]initWithFrame:frame];  
    theView.backgroundColor = [UIColor blackColor];  
    theView.alpha = 0.7;  
      
    [progress setTag:100];  
    [theView addSubview:progress];  
    [showValue setTag:101];  
    [theView addSubview:showValue];  
      
    [theView addSubview:progressInd];  
    [theView addSubview:waitinglabel];  
[theView setTag:110];  
    [self.view addSubview:theView];  
}  
  
//隐藏等待框  
-(void)hiddenWaiting{  
    [[self.view viewWithTag:110]removeFromSuperview];  
}  
  
- (void)viewDidUnload  
{  
    [super viewDidUnload];  
    // Release any retained subviews of the main view.  
}  
  
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation  
{  
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);  
}  
  
#pragma mark DownLoadImageDelegate methods  
//展示下载完毕的图片  
-(void)imageDownLoadFinished:(UIImage *)img{  
//退出等待框  
    [self hiddenWaiting];  
    [appImgView setImage:img];  
}  
  
//更新进度条的值  
-(void)updateDownProgress:(double) value{  
    UIProgressView *progresss = (UIProgressView *)[self.view viewWithTag:100];  
    UILabel *showValue = (UILabel*)[self.view viewWithTag:101];  
    progresss.progress = value;  
    showValue.text = [NSString stringWithFormat:@"%.1f%",(double)(value*100)];  
}  
  
@end

3、效果如下:

抱歉!评论已关闭.