1 从内存中取出,判断是否存在,如果存在直接赋值给cell的imageView;不存在进入第二步;
2 去沙河中去取出
如果存在
2.1 给cell的imageView赋值
2.2 将图片加入到内存缓存中,提高性能
如果不存在,进入第三步;
3. 为了不重复发请求,每次发送网络请求时用一个可变字典记录下来,所以每次发送请求之前要判断一下当前请求是否已经存在,如果存在直接返回
4. 如果图片在缓存和内存中都不存在,新开启一个线程,下载图片
4.1保存到沙盒
4.2 保存到内存
4.3删除本次操作记录
4.4刷新表格
4.5把操作加入到操作缓存中,避免重复下载
4.6 把操作加入到队列中下载
具体参照如下代码
//
// WJLTableViewController.m
// 如何争取的加载图片
//
// Created by Wangjunling on 16/3/23.
// Copyright © 2016年 Wangjunling. All rights reserved.
//
#import "WJLTableViewController.h"
#import "WJLAppInfo.h"
#import "WJLTableViewCell.h"
#import "NSString+Path.h"
@interface WJLTableViewController ()
/** 数据 */
@property (nonatomic, strong) NSArray *appInfos;
/** 队列 */
@property (nonatomic, strong) NSOperationQueue *queue;
/** 操作缓存 */
@property (nonatomic, strong) NSMutableDictionary *operationCache;
//内存缓存集合
@property(nonatomic,strong) NSMutableDictionary *menCache;
@end
@implementation WJLTableViewController
#pragma mark - 懒加载
- (NSArray *)appInfos {
if (_appInfos == nil) {
_appInfos = [WJLAppInfo applist];
}
return _appInfos;
}
- (NSOperationQueue *)queue {
if (_queue == nil) {
_queue = [NSOperationQueue new];
}
return _queue;
}
-(NSMutableDictionary *)operationCache{
if(!_operationCache){
_operationCache = [NSMutableDictionary dictionary];
}
return _operationCache;
}
-(NSMutableDictionary *)menCache{
if(!_menCache){
_menCache = [NSMutableDictionary dictionary];
}
return _menCache;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.appInfos.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"appCell" forIndexPath:indexPath];
WJLAppInfo *appInfo = self.appInfos[indexPath.row];
// 1 从内存中取出
UIImage *image = self.menCache[appInfo.icon];
if (image) {//内存缓存存在,给cell的图片赋值
cell.imageView.image = image;
return cell;
} else {//2.否则去沙河中去取出
UIImage *sandBoxImage = [UIImage imageWithContentsOfFile:[appInfo.icon appendCachePath]];
if(sandBoxImage){
cell.imageView.image = image;
//加入到内存缓存中,提高性能
[self.menCache setValue:sandBoxImage forKey:appInfo.icon];
return cell;
}
}
//3. 为了不重复发请求,每次发送网络请求时用一个可变字典记录下来,所以每次发送请求之前要判断一下当前请求是否已经存在,如果存在直接返回
if(self.operationCache[appInfo.icon]){
return cell;
}
//4. 如果图片在缓存和内存中都不存在,新开启一个线程,下载图片
NSBlockOperation *downLoadOperation = [NSBlockOperation blockOperationWithBlock:^{
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:appInfo.icon]];
//4.1 保存到沙盒
[data writeToFile:[appInfo.icon appendCachePath] atomically:true];
UIImage *image = [UIImage imageWithData:data];
if(!image){
return;
}
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
//4.2 保存到内存
[self.menCache setValue:image forKey:appInfo.icon];
//4.3 删除本次操作记录
[self.operationCache removeObjectForKey:appInfo.icon];
//4.4 刷新表格
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}];
}];
//4.5 把操作加入到操作缓存中
[self.operationCache setValue:downLoadOperation forKey:appInfo.icon];
//4.6 把操作加入到队列中
[self.queue addOperation:downLoadOperation];
return cell;
}
@end
以上代码 ,其实还有一个问题, 就是循环引用的问题, 在block中使用self时会引起循环引用,要解决这个问题需要弱化self 在多线程任务前面加入
__weak typeof(self) weakself = self;
保险起见所有block中的self 全部替换成weakself