一个下载操作就交给一个HMDownloadOperation对象
HMDownloadOperation.h / .m
@class HMDownloadOperation;@protocol HMDownloadOperationDelegate@optional- (void)downloadOperation:(HMDownloadOperation *)operation didFinishDownload:(UIImage *)image;@end@interface HMDownloadOperation : NSOperation@property (nonatomic, copy) NSString *url;@property (nonatomic, strong) NSIndexPath *indexPath;@property (nonatomic, weak) id delegate;@end
#import "HMDownloadOperation.h"@implementation HMDownloadOperation/** * 在main方法中实现具体操作 */- (void)main{ @autoreleasepool { NSURL *downloadUrl = [NSURL URLWithString:self.url]; NSData *data = [NSData dataWithContentsOfURL:downloadUrl]; // 这行会比较耗时 UIImage *image = [UIImage imageWithData:data]; if ([self.delegate respondsToSelector:@selector(downloadOperation:didFinishDownload:)]) { dispatch_async(dispatch_get_main_queue(), ^{ // 回到主线程, 传递图片数据给代理对象 [self.delegate downloadOperation:self didFinishDownload:image]; }); } }}
控制器View 调用
@interface HMViewController ()@property (nonatomic, strong) NSArray *apps;@property (nonatomic, strong) NSOperationQueue *queue;/** key:url value:operation对象 */@property (nonatomic, strong) NSMutableDictionary *operations;/** key:url value:image对象*/@property (nonatomic, strong) NSMutableDictionary *images;@end@implementation HMViewController- (NSArray *)apps{ if (!_apps) { NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil]]; NSMutableArray *appArray = [NSMutableArray array]; for (NSDictionary *dict in dictArray) { HMApp *app = [HMApp appWithDict:dict]; [appArray addObject:app]; } _apps = appArray; } return _apps;}- (NSOperationQueue *)queue{ if (!_queue) { _queue = [[NSOperationQueue alloc] init]; _queue.maxConcurrentOperationCount = 3; // 最大并发数 == 3 } return _queue;}- (NSMutableDictionary *)operations{ if (!_operations) { _operations = [NSMutableDictionary dictionary]; } return _operations;}- (NSMutableDictionary *)images{ if (!_images) { _images = [NSMutableDictionary dictionary]; } return _images;}- (void)viewDidLoad{ [super viewDidLoad]; }#pragma mark - 数据源方法- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.apps.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *ID = @"app"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; } HMApp *app = self.apps[indexPath.row]; cell.textLabel.text = app.name; cell.detailTextLabel.text = app.download; // 显示图片 // 保证一个url对应一个HMDownloadOperation // 保证一个url对应UIImage对象 UIImage *image = self.images[app.icon]; if (image) { // 缓存中有图片 cell.imageView.image = image; } else { // 缓存中没有图片, 得下载 cell.imageView.image = [UIImage imageNamed:@"57437179_42489b0"]; HMDownloadOperation *operation = self.operations[app.icon]; if (operation) { // 正在下载 // ... 暂时不需要做其他事 } else { // 没有正在下载 // 创建操作 operation = [[HMDownloadOperation alloc] init]; operation.url = app.icon; operation.delegate = self; operation.indexPath = indexPath; [self.queue addOperation:operation]; // 异步下载 self.operations[app.icon] = operation; } } // SDWebImage : 专门用来下载图片 return cell;}#pragma mark - HMDownloadOperationDelegate- (void)downloadOperation:(HMDownloadOperation *)operation didFinishDownload:(UIImage *)image{ // 1.移除执行完毕的操作 [self.operations removeObjectForKey:operation.url]; if (image) { // 2.将图片放到缓存中(images) self.images[operation.url] = image; // 3.刷新表格 [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationNone]; // 3.将图片写入沙盒// NSData *data = UIImagePNGRepresentation(image);// [data writeToFile:@"" atomically:<#(BOOL)#>]; } }- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{ // 开始拖拽 // 暂停队列 [self.queue setSuspended:YES];}- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{ [self.queue setSuspended:NO];}@end