iOS学习笔记-131.多线程24——多图下载4_第四种实现方式(缓存使用NSCache)

多线程24——多图下载4_第四种实现方式(缓存使用NSCache)

一、修改与说明

这种方式的修改是在 iOS学习笔记-123.多线程22——多图下载2_第二种实现方式(三级缓存) 的基础上修改的。

前面我们使用了 字典 做内存缓存,现在我们改为 NSCache 来做内存缓存。

之前在 iOS学习笔记-130.NSCache使用 中我们说过 NSCache的使用和字典几乎是一样的,只有部分区别。

于是,我们这里只需要修改 images 这个缓存属性的 类型,和实例化时候的方法。

修改如下

1.

/** 内存缓存 */
@property (nonatomic, strong) NSMutableDictionary *images;

修改为

/** 内存缓存 */
@property (nonatomic, strong) NSCache *images;

2.

-(NSMutableDictionary*)images{
    if(_images==nil){
        _images = [NSMutableDictionary dictionary];
    }
    return _images;
}

修改为,这里面我们加了缓存数量的限制

-(NSCache*)images{
    if(_images==nil){
        _images = [NSCache new];
        //最大缓存10张图片
        _images.countLimit = 10;
    }
    return _images;
}

二、代码

//
//  ViewController.m
//  03_UIview86多线程_多图下载
//
//  Created by 杞文明 on 17/9/6.
//  Copyright © 2017年 杞文明. All rights reserved.
//

#import "ViewController.h"
#import "QWMAppItem.h"
#import "NSString+MD5.h"
#import "UIImageView+WebCache.h"

@interface ViewController ()
/** tableView的数据源 */
@property (nonatomic, strong) NSArray *apps;
/** 内存缓存 */
@property (nonatomic, strong) NSCache *images;
/** 队列 */
@property (nonatomic, strong) NSOperationQueue *queue;
/** 操作缓存 */
@property (nonatomic, strong) NSMutableDictionary *operations;
@end

@implementation ViewController

-(NSArray*)apps{
    if(_apps==nil){
        //字典数据
        NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil]];
        //字典数据转模型数据
        NSMutableArray *arrM = [NSMutableArray array];
        for (NSDictionary *dict in array) {
            [arrM addObject:[QWMAppItem appWitdDict:dict]];
        }
        _apps = arrM;
    }
    return _apps;
}

-(NSCache*)images{
    if(_images==nil){
        _images = [NSCache new];
        //最大缓存10张图片
        _images.countLimit = 10;
    }
    return _images;
}

-(NSOperationQueue *)queue{
    if(_queue == nil){
        _queue = [[NSOperationQueue alloc]init];
        //设置最大并发数
        _queue.maxConcurrentOperationCount = 5;
    }
    return _queue;
}

-(NSMutableDictionary *)operations{
    if(_operations == nil){
        _operations = [NSMutableDictionary dictionary];
    }
    return _operations;
}

/*组数*/
-(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* identifier = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    //获取数据
    QWMAppItem *appItem = self.apps[indexPath.row];

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

    [self handle2:cell withItem:appItem withIndex:indexPath];

    return cell;
}

/*图片的第二种种处理方式*/
-(UITableViewCell*)handle2:(UITableViewCell*)cell withItem:(QWMAppItem*)appItem withIndex:(NSIndexPath*)indexPath{
    //1.首先判断内存中是否已经存在,存在直接取
    //2.内存中不存在,判断本地是否存在,存在直接取。
    //3.本地不存在,判断当前的图片是否已经添加到任务中,如果是,那么不操作
    //4.如果没有添加到任务中,那么我们把下载图片的操作添加到任务中

    //获取我们图片地址的MD5值作为唯一标识符 MD5+后缀名
    NSString *imageID = [NSString stringWithFormat:@"%@.%@",[appItem.icon MD5_32BitLower],[appItem.icon pathExtension]];
    UIImage *image = [self.images objectForKey:imageID];

    if(image){
        //使用内存缓存
        cell.imageView.image = image;
         NSLog(@"%zd处的图片使用了内存缓存中的图片",indexPath.row);

    }else{
        //1.获取沙盒的路径
        NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
//        NSLog(@"%@",caches);
        //2.拼接我们图片的地址
        NSString * imageFullPath = [caches stringByAppendingPathComponent:imageID];
        //3.获取本地磁盘中的图片数据
        NSData *imageData = [NSData dataWithContentsOfFile:imageFullPath];
        //4.判断数据是否已经存在,存在说明我们有本地缓存,那么我们直接拿来显示
        if (imageData) {
            //使用本地缓存
            cell.imageView.image = [UIImage imageWithData:imageData];
            NSLog(@"%zd处的图片使用了本地缓存中的图片",indexPath.row);
        }else{
            //都没有,那么我们就需要去网络下载了
            //我们获取先去判断一下,我们的这个图片下载任务是否已经在队列中存在,如果有不操作,没有那么我们添加一个下载任务
            NSBlockOperation *download = [self.operations objectForKey:imageID];
            if(!download){//没有这个任务,那么我们就添加任务
                //为了解决滑动时候数据显示错乱,我们现在添加一张图片,用于做默认显示
                cell.imageView.image = [UIImage imageNamed:@"image1"];
                //创建现在任务
                download = [NSBlockOperation blockOperationWithBlock:^{
                    //下载
                    NSURL *url = [NSURL URLWithString:appItem.icon];
                    NSData *imageData = [NSData dataWithContentsOfURL:url];
                    UIImage *image = [UIImage imageWithData:imageData];

                    //容错处理
                    if (image == nil) {
                        //如果这个下载有误,那么我们不操作了,并且从操作缓存中移除,为了下一次还能下载
                        [self.operations removeObjectForKey:imageID];
                        return ;
                    }
                    //下载好了,现在需要如下操作
                    //1.数据添加到内存缓存中
                    //2.数据添加到本地中(本地缓存)
                    //3.主线程中显示数据
                    [self.images setObject:image forKey:imageID];//内存缓存
                    [imageData writeToFile:imageFullPath atomically:YES];//本地缓存
                    [[NSOperationQueue mainQueue] addOperation:[NSBlockOperation blockOperationWithBlock:^{//主线程显示,就是去刷新这一行
                        [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
                    }]];
                    //下载已经好了,那么移除图片下载操作
                    [self.operations removeObjectForKey:imageID];
                }];

                //把任务添加到队列中
                [self.queue addOperation:download];
                //添加任务到操作缓存中,等到下载好了再把它移除
                [self.operations setObject:download forKey:imageID];
            }
        }
    }
    return cell;
}


/*内存警告*/
-(void)didReceiveMemoryWarning{
    //内存不存的时候删除我们的缓存
    [self.operations removeAllObjects];
    [self.images removeAllObjects];
}

@end

三、图示

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值