自定义NSOperation
来源:互联网 发布:电话号码数据 编辑:程序博客网 时间:2024/05/22 03:30
上一节,我对NSOperation的基本概念及使用进行了介绍,想要了解的,请点击这里。本节中,我介绍自定义NSOperation实现多线程异步下载图片,类似于SDWebImage。
自定义NSOperation的步骤很简单,重写 - (void)main方法,在里面实现想执行的任务。
重写 - (void)main方法注意点:
1.自己创建自动释放池(因为如果是异步操作,无法访问主线程的自动释放池)
2.经常通过 - (BOOL)isCancelled 方法检测操作是否被取消,对取消做出响应。
Demo最终的效果图:
上面的图片均是通过NSOperation异步下载的。
下面,我具体介绍代码的实现过程。
1.首先,我准备了数据源(data.plist文件)
2. 定义了对应的数据模型
@interface DataModel : NSObject/* 图片名称 */@property (nonatomic,copy) NSString *name;/* 图片url地址 */@property (nonatomic,copy) NSString *url;/* 下载次数 */@property (nonatomic,strong) NSNumber *downloadedCount;// 字典转化为模型- (instancetype)initWithDict:(NSDictionary *)dict;@end@implementation DataModel- (instancetype)initWithDict:(NSDictionary *)dict { if (self = [super init]) { // (KVC)字典转模型 [self setValuesForKeysWithDictionary:dict]; } return self;}@end
3. ViewController中得代码:
#import "ViewController.h"#import "DataModel.h"#import "LFDownloadOperation.h"@interface ViewController ()<LFDownloadOperationDelegate>/* 数据源 */@property (nonatomic,strong) NSMutableArray *dataLists;// Key:url, Value: UIImage (存放图片的缓存字典,有的话,直接取出使用;没有的话,下载)@property (nonatomic,strong) NSMutableDictionary *images;// Key:url, Value: LFDownloadOperation@property (nonatomic,strong) NSMutableDictionary *operations;// 下载队列,存放LFDownloadOperation@property (nonatomic,strong) NSOperationQueue *queue;@end@implementation ViewController#pragma mark - Lazy Load- (NSMutableArray *)dataLists { if (!_dataLists) { NSString *file = [[NSBundle mainBundle] pathForResource:@"data" ofType:@"plist"]; NSArray *dataArr = [NSArray arrayWithContentsOfFile:file]; NSMutableArray *tempLists = [NSMutableArray array]; for (NSDictionary *dict in dataArr) { DataModel *model = [[DataModel alloc] initWithDict:dict]; [tempLists addObject:model]; } _dataLists = tempLists; } return _dataLists;}- (NSMutableDictionary *)images { if (!_images) { _images = [NSMutableDictionary dictionary]; } return _images;}- (NSMutableDictionary *)operations { if( !_operations) { _operations = [NSMutableDictionary dictionary]; } return _operations;}- (NSOperationQueue *)queue { if (!_queue) { _queue = [[NSOperationQueue alloc] init]; } return _queue;}- (void)viewDidLoad { [super viewDidLoad];}#pragma mark - UITableView Delegate/DataSource- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.dataLists.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *identifer = @"UITableViewCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifer]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifer]; } DataModel *model = self.dataLists[indexPath.row]; cell.textLabel.text = model.name; cell.detailTextLabel.text = [model.downloadedCount stringValue]; // 主要实现下载的代码 UIImage *image = self.images[model.url]; if (image) { // 图片下载完毕(在字典中) cell.imageView.image = image; } else { // 创建下载Operation并设置默认占位图片 LFDownloadOperation *operation = self.operations[model.url]; cell.imageView.image = [UIImage imageNamed:@"placeholder.jpg"]; // 如果operation有值,说明正在下载 if (!operation) { // 还没有下载,立刻创建operation并下载 operation = [[LFDownloadOperation alloc] init]; operation.delegate = self; operation.url = model.url; operation.indexPath = indexPath; // 将每张图片的下载地址和每个opearion建立对应关系 self.operations[model.url] = operation; // 不能在这里创建队列,应该只创建一个队列(所以使用懒加载) //NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 加到队列中并下载 [self.queue addOperation:operation]; } } return cell;}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 130;}#pragma mark - LFDownloadOperationDelegate- (void)downloadOperation:(LFDownloadOperation *)operation didFinishedWithImage:(UIImage *)image { NSIndexPath *indexPath = operation.indexPath; DataModel *model = self.dataLists[indexPath.row]; // 当一张图片下载完成了,则应该移除这张图片对应的operation [self.operations removeObjectForKey:model.url]; // 将下载完成的图片保存到images这个字典缓存池中 self.images[model.url] = image; // 每次有图片下载完成,则刷新对应的cell并显示图片 [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];}@end
4. 自定义的NSOperation
@class LFDownloadOperation;@protocol LFDownloadOperationDelegate <NSObject>@optional/* 代理返回下载完毕的图片 */- (void)downloadOperation:(LFDownloadOperation *)operation didFinishedWithImage:(UIImage *)image;@end@interface LFDownloadOperation : NSOperation@property (nonatomic,copy) NSString *url;@property (nonatomic,strong) NSIndexPath *indexPath;@property (nonatomic,assign) id<LFDownloadOperationDelegate> delegate;@end@implementation LFDownloadOperation// NSOperation中的main就是实现相应的异步操作,所以重写父类方法- (void)main{ // 因为LFDownloadOperation已经不在主线程的自动释放池了,所以要包含在@autoreleasepool中 @autoreleasepool { // 取消操作发生在任何时刻都有可能,因此在执行任何操作之前,先检测该操作是否已经被取消 if (self.isCancelled) { return; } NSURL *url = [NSURL URLWithString:self.url]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; if (self.isCancelled) { return; } if ([self.delegate respondsToSelector:@selector(downloadOperation:didFinishedWithImage:)]){ dispatch_async(dispatch_get_main_queue(), ^{ // 最后将异步下载完成的图片返回到主线程(dispatch_get_main_queue) [self.delegate downloadOperation:self didFinishedWithImage:image]; }); } }}@end
0 0
- 自定义NSOperation
- 自定义 NSOperation
- NSOperation自定义
- 自定义NSOperation
- 自定义NSOperation
- 自定义 NSOperation
- 自定义NSOperation
- 自定义NSOperation
- 71 自定义NSOperation
- 自定义NSOperation 下载图片
- 233,自定义NSOperation
- iOS开发 自定义NSOPeration
- 自定义NSOperation(二)
- iOS开发多线程-自定义NSOperation
- iOS开发之自定义NSOperation
- 继承NSOperation-自定义同步 operation
- 继承NSOperation-自定义异步 Operation
- 《多线程——自定义NSOperation》
- 分析如何查找Linux死机的原因
- windows与Linux间远程拷贝文件-pscp命令
- OJ矩形类定义(C++)
- C语言全排列
- Know Your IDE
- 自定义NSOperation
- 从data.dat文件中读取整数求和,结果保存到same.data文件中
- discuz 从win7迁移到centos6.5(lnmp环境),遇到的问题
- 深入阅读
- 5,13 第8周项目 5 友元类
- 第九周(运算符重载分数类)
- Know Your Limits
- Know Your Next Commit
- Java容器类Collection、List、ArrayList、Vector及map、HashTable、HashMap区别