首页 > 代码库 > iOS多线程自定义operation加载图片 不重复下载图片
iOS多线程自定义operation加载图片 不重复下载图片
摘要:1:ios通过抽象类NSOperation封装了gcd,让ios的多线程变得更为简单易用;
2:耗时的操作交给子线程来完成,主线程负责ui的处理,提示用户的体验
2:自定义operation继承自NSOperation,在子线程中下载图片;
3:保证图片只下载一次,还有保证下载任务不重复
------------------------------------------------------------------------------------
实现原理:1:图片缓存:用字典保存图片和图片的url,key:url value:图片
2:任务缓存:用字典保存operation任务和图片的url,key:url value:operation
先看自定义的operation:.h文件
1 #import <Foundation/Foundation.h> 2 @class XBOperation; 3 4 @protocol XBOperationDelegate <NSObject> 5 6 -(void)operation:(XBOperation *)operation didFinishDownloadImage:(UIImage *)image; 7 8 @end 9 /**10 * 自定义operation11 */12 @interface XBOperation : NSOperation13 14 // 代理15 @property (nonatomic, weak)id<XBOperationDelegate> delegate;16 17 /**18 * url19 */20 @property (nonatomic, copy) NSString *url;21 /**22 * indexPath 和tableview中的cell相对应23 */24 @property (nonatomic, strong) NSIndexPath *indexPath;25 26 @end
说明:设置代理的目的是等完成下载图片的后通知控制器拿图片
自定义operation的.m文件
@implementation XBOperation-(void)main{ if (self.isCancelled) return; NSURL *downloadUrl = [NSURL URLWithString:self.url]; NSData *data = http://www.mamicode.com/[NSData dataWithContentsOfURL:downloadUrl]; // 这行会比较耗时 if (self.isCancelled) return; UIImage *image = [UIImage imageWithData:data]; if (self.isCancelled) return; NSLog(@"--%@--", [NSThread currentThread]); if ([self.delegate respondsToSelector:@selector(operation:didFinishDownloadImage:)]) { dispatch_async(dispatch_get_main_queue(), ^{ // 回到主线程, 传递图片数据给代理对象 [self.delegate operation:self didFinishDownloadImage:image]; }); }}@end
说明:重写main方法,在把任务operation加入到队列后,队列会自动调用任务的start方法,start方法内部会调用main方法来完成操作
控制器的tableviewcell数据源的实现
#pragma mark dataSource数据源方法-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1;}-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.apps.count;}// 数据源方法 实现cell中的内容填充-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *ID = @"app"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]; } // 设置数据 XBApp是数据模型 XBApp *app = self.apps[indexPath.row]; // 设置标题和子标题 cell.textLabel.text = app.name; cell.detailTextLabel.text = app.download; cell.imageView.image = [UIImage imageNamed:@"57437179_42489b0"]; // 图片数据设置 UIImage *image = self.imageCache[app.icon]; if (image) { // 如果图片缓存中有图片 直接加载到 cell.imageView.image = image; }else{ // 如果缓存中没有数据 // 先设置占位占位图片 cell.imageView.image = [UIImage imageNamed:@"57437179_42489b0"]; // 创建自定义的operation 先根据当前要显示图片的url从队列中找到operation 看是否正在下载中 XBOperation *operationDown = self.operationQueue[app.icon]; if (!operationDown) { // 如果下载operation不存在 就创建 并添加到队列中 operationDown = [[XBOperation alloc] init]; operationDown.delegate = self; // 设置代理 operationDown.indexPath = indexPath; // 把每个cell与一个operation绑定 operationDown.url = app.icon; // 把operation添加到队列中 会自动调用start方法 然后调用operation的main的方法 [self.queue addOperation:operationDown]; // 把operation这个下载任务添加到operation的字典中 防止重复下载 self.operationQueue[app.icon] = operationDown; } } return cell; }// 实现代理方法-(void)operation:(XBOperation *)operation didFinishDownloadImage:(UIImage *)image{ // 必须清楚当前operation 防止由于网络等原因造成的下载失败 而operation还在字典中 这样永远下载不了 [self.operationQueue removeObjectForKey:operation.url]; if (image) { // 将图片放在缓存字典中 self.imageCache[operation.url] = image; // 刷新表格 单行刷新 [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationNone]; }}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。