一个下载操作就交给一个HMDownloadOperation对象
HMDownloadOperation.h / .m
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
@class HMDownloadOperation; @protocol HMDownloadOperationDelegate <NSObject> @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<HMDownloadOperationDelegate> delegate; @end
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#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 () <HMDownloadOperationDelegate> @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