第03天多线程网络:(11):多图下载程序应用NSCache

原创
2017/04/24 14:32
阅读数 5

#####一、多图下载程序应用NSCache

NSCache 和 NSMutableDictionary 基本相同
NSCache比NSMutableDictionary 多了几个属性 
totalCostLimit 总成本 (如果发现存的数据超过总成本,那么会自定回收之前的对象)
countLimit 设置最多可以缓存多少个数据 (如果当前数据大于这个数据 ,那么重新加载)


code NSCache简单介绍 VC

#import "ViewController.h"
#import "LYHAppModel.h"

@interface ViewController ()

/** 数组源 */
// 如何选择使用 可变还是不可变 是根据需求来说的
// 如果数据是固定的 那么就用 不可变的
// 如果数据是不固定 那么就用 可变的

@property(nonatomic, strong) NSArray *dataA;
/** 内存缓存 */
// 每下载完一张图片 要保存起来
//@property(nonatomic, strong) NSMutableDictionary *dict_images;
@property(nonatomic, strong) NSCache *dict_images;

/** 队列(用来下载任务) */
@property(nonatomic, strong)NSOperationQueue *queue;

/* 图片下载操作缓存 */
@property(nonatomic, strong) NSMutableDictionary *dict_operations;

@end

@implementation ViewController
#pragma mark 懒加载
- (NSMutableDictionary *)dict_operations
{
    if (_dict_operations == nil) {
        _dict_operations = [NSMutableDictionary dictionary];
    }
    return _dict_operations;
}

- (NSOperationQueue *)queue
{
    if (_queue == nil) {
        _queue = [[NSOperationQueue alloc]init];
        // 在程序里面 最好只开3~5个队列
        // 设置队列并发数
        _queue.maxConcurrentOperationCount = 5;
    }
    return  _queue;
}

- (NSCache *)dict_images
{
    if (_dict_images == nil) {
        _dict_images = [[NSCache alloc]init];
        // 设置最多可以缓存多少个数据
        _dict_images.countLimit =  4;
    }
    return _dict_images;
}

- (NSArray *)dataA
{
    if (_dataA == nil) {
        
        // 字典数组
        NSArray *arr = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil]];
        NSMutableArray *arrM = [NSMutableArray array];
        for (NSDictionary *dict in arr) {
            [arrM addObject:[LYHAppModel LYHAppModelWithDict:dict]];
        }
        _dataA = arrM;
        
    }
    return _dataA;
}
- (void)viewDidLoad
{
    [super viewDidLoad];
}

#pragma mark --- ---
#pragma mark tableViewDataScoure
// 多少组
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

// 多少行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.dataA.count;
}

// cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 1.创建cell
    static NSString *ID = @"app";
    // 2.设置cell数据
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    // 拿到该行cell的数据
    LYHAppModel *model = [self.dataA objectAtIndex:indexPath.row];
    // 设置数据

    cell.textLabel.text = model.name;
    cell.detailTextLabel.text = model.download;

    
    //2.4 先去内存缓存中,该图片是否存在,如果存在,那么就直接拿到用,否则去检查磁盘缓存
    // 如果有磁盘缓存,那么保存一份到内存,设置图片,否则就直接下载
    // 1)没有下载过
    // 2)重新打开程序 (先去判断内存缓存有没有,没有再去磁盘缓存里面查找,找到了还需要保存到内存缓存里面)
    
    UIImage *image = [self.dict_images objectForKey:model.icon];
    if (image) {
        cell.imageView.image = image;
        NSLog(@"--%zd的图片使用内存缓存图片",indexPath.row);

    }
    else
    {

        NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
        NSString *fileName = [model.icon lastPathComponent]; // 获取文件的最后节点
        NSString *fullPath = [caches stringByAppendingPathComponent:fileName];
        //NSLog(@" fullPath %@",fullPath);
        
        // 检查磁盘缓存(是否存在)
        NSData *imageData = [NSData dataWithContentsOfFile:fullPath];
        // 废除磁盘缓存
        imageData = nil;
        if (imageData)
        {
            UIImage *image = [UIImage imageWithData:imageData];
            cell.imageView.image = image;
            NSLog(@"--%zd的图片使用磁盘缓存图片",indexPath.row);

            // 1.把图片保存到内存缓存
            [self.dict_images setObject:image forKey:model.icon];
        }
        else
        {
            // 不存在
            // 检查该图片是否正在下载(如果是 ,那么什么都不做,否则再添加下载操作)
            NSBlockOperation *downloadOp = [self.dict_operations objectForKey:model.icon];
            
            if (downloadOp) {
                // 下载操作 存在
                // 什么都不做
            }
            else
            {
                // 先清空cell原来的图片
                cell.imageView.image = [UIImage imageNamed:@"lyh165"]; // 占位图片
                //            NSOperationQueue *queue = [[NSOperationQueue alloc]init]; // 1.非主队列
                downloadOp = [NSBlockOperation blockOperationWithBlock:^{
                    NSURL *url = [NSURL URLWithString:model.icon];
                    NSData *imageData = [NSData dataWithContentsOfURL:url];
                    UIImage *image = [UIImage imageWithData:imageData];
                    //                NSLog(@"---download --%@",[NSThread currentThread]);
                    
#pragma UI刷新的操作
                    NSLog(@"%zd---下载-- ",indexPath.row);

                    // 容错处理
                    // 可能服务器返回的URL不对
                    if (image == nil) {
                        // 为了服务器能够改过来,我们还需要处理
                        // 移除当前的key
                        [self.dict_operations removeObjectForKey:model.icon];
                        return ;
                    }
                    
                    
                    // 演示网速慢的情况
//                    [NSThread sleepForTimeInterval:2.0];
                    // 1.把图片保存到内存缓存(演示网速慢的情况 会闪退)
                    [self.dict_images setObject:image forKey:model.icon];
                    
                    // 线程之间的通信
                    [[NSOperationQueue mainQueue]addOperationWithBlock:^{
                        // [self.tableView reloadData]; 刷新整个tableview
                        // 刷新某一行
                        [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
                        cell.imageView.image = image;
                        //                    NSLog(@"---UI --%@",[NSThread currentThread]);
                    }];
                    
                    
                    
                    /*
                     参数1 : 写到那个位置
                     参数2 : 表示原子性
                     */
                    [imageData writeToFile:fullPath atomically:YES];
                    
                    
                    // 图片下载完之后,移除下载操作
                    [self.dict_operations removeObjectForKey:model.icon];
                    
                }]; // 2.封装操作
                
                
                // 添加操作 到 操作缓存中
                [self.dict_operations setObject:downloadOp forKey:model.icon];
                // 3.添加操作到队列中
                [self.queue addOperation:downloadOp];
            }
        }

    }

    
    return cell;
}

#pragma mark tableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    
    NSArray *arr = self.dataA;
    // 检查缓存数量
    for (NSInteger i = 0; i<arr.count; i++) {
        LYHAppModel *model = arr[i];
        
        UIImage *img = [self.dict_images objectForKey:model.icon];
        
        if (img) {
            NSLog(@"存储图片缓存 %zd",i);
            
        }
    }
}



@end
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部