NSOperation
NSOperationQueue
的使用
apps.plist
ZYXApp.h
#import <Foundation/Foundation.h>
@interface ZYXApp : NSObject
/** 图标 */
@property (nonatomic, strong) NSString *icon;
/** 下载量 */
@property (nonatomic, strong) NSString *download;
/** 名字 */
@property (nonatomic, strong) NSString *name;
+ (instancetype)appWithDict:(NSDictionary *)dict;
@end
ZYXApp.m
#import "ZYXApp.h"
@implementation ZYXApp
+ (instancetype)appWithDict:(NSDictionary *)dict
{
ZYXApp *app = [[self alloc] init];
[app setValuesForKeysWithDictionary:dict];
return app;
}
@end
ViewController.m
#import "ViewController.h"
#import "ZYXApp.h"
@interface ViewController ()
/** 所有数据 */
@property (nonatomic, strong) NSArray *apps;
/** 内存缓存的图片 url-image对象 */
@property (nonatomic, strong) NSMutableDictionary *images;
/** 所有的操作对象 url-NSOperation对象 */
@property (nonatomic, strong) NSMutableDictionary *operations;
/** 队列对象 */
@property (nonatomic, strong) NSOperationQueue *queue;
@end
@implementation ViewController
- (NSOperationQueue *)queue
{
if (!_queue) {
_queue = [[NSOperationQueue alloc] init];
_queue.maxConcurrentOperationCount = 3;
}
return _queue;
}
- (NSMutableDictionary *)operations
{
if (!_operations) {
_operations = [NSMutableDictionary dictionary];
}
return _operations;
}
- (NSMutableDictionary *)images
{
if (!_images) {
_images = [NSMutableDictionary dictionary];
}
return _images;
}
- (NSArray *)apps
{
if (!_apps) {
NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil]];
NSMutableArray *appArray = [NSMutableArray array];
for (NSDictionary *dict in dictArray) {
[appArray addObject:[ZYXApp appWithDict:dict]];
}
_apps = appArray;
}
return _apps;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
self.images = nil;
self.operations = nil;
[self.queue cancelAllOperations];
}
#pragma mark - 数据源方法
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (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 == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
}
ZYXApp *app = self.apps[indexPath.row];
cell.textLabel.text = app.name;
cell.detailTextLabel.text = app.download;
// 先从内存缓存中取出图片
UIImage *image = self.images[app.icon];
if (image) { // 内存中有图片
cell.imageView.image = image;
} else { // 内存中没有图片
// 获得Library/Caches文件夹
NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
// 获得文件名
NSString *filename = [app.icon lastPathComponent];
// 计算出文件的全路径
NSString *file = [cachesPath stringByAppendingPathComponent:filename];
// 加载沙盒的文件数据
NSData *data = [NSData dataWithContentsOfFile:file];
if (data) { // 直接利用沙盒中图片
UIImage *image = [UIImage imageWithData:data];
cell.imageView.image = image;
// 存到字典中
self.images[app.icon] = image;
} else { // 下载图片
cell.imageView.image = [UIImage imageNamed:@"placeholder"];
NSOperation *operation = self.operations[app.icon];
if (operation == nil) { // 这张图片暂时没有下载任务
operation = [NSBlockOperation blockOperationWithBlock:^{
// 下载图片
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]];
// 数据加载失败
if (data == nil) {
// 移除操作
[self.operations removeObjectForKey:app.icon];
return;
}
UIImage *image = [UIImage imageWithData:data];
// 存到字典中
self.images[app.icon] = image;
// 回到主线程显示图片
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}];
// 将图片文件数据写入沙盒中
[data writeToFile:file atomically:YES];
// 移除操作
[self.operations removeObjectForKey:app.icon];
}];
// 添加到队列中
[self.queue addOperation:operation];
// 存放到字典中
self.operations[app.icon] = operation;
}
}
}
return cell;
}
@end
下载的图片在沙盒的保存地址:
/Users/admin/Library/Developer/CoreSimulator/Devices/95A0E48B-2AF9-45A0-83AE-6C065C293B5E/data/Containers/Data/Application/8279B407-F09D-4FD8-99F1-7695B1F9FDC1/Library/Caches