美文网首页
图片缓存

图片缓存

作者: 闲得一B | 来源:发表于2016-05-02 20:16 被阅读99次
    SDWebImage框架是为UIImageView添加的一个分类,提供了远程图片下载的缓存机制。
    缓存机制大概的思路:
    1、提供两个字典,一个字典中用将图片的URL作为Key图片作为value来保存,用来做内存缓存。还有一个字典将图片的URL作为Key下载图片的操作作为value。
    2、首先根据URL去缓存中找是否有图片。
    3、缓存中没有就去沙盒中查找是否有图片(根据URL的MD5生成唯一的图片名字)。
    4、当沙盒中没有暂时设置占位图片。(设置占位图片的另一个原因是设置图片的尺寸)
    5、发送请求,从网络中获取图片。
    6、根据URL判断当前操作有没有正在下载。
    7、没有下载,创建一个操作添加到队列中来异步下载图片,并将这个操作存放到字典中
    8、下载失败,移除字典中的下载操作(防止下次不能下载),并返回。
    9、下载成功,将图片放入缓存中。
    10、回到主线程刷新`添加操作`这一行的cell(不直接设置图片的原因是防止循环利用显示出错)。
    11、将图片写入沙盒(耗时操作尽量放到后面)。
    12、移除操作。
    

    #import <Foundation/Foundation.h>
    
    @interface XDYBApp : NSObject
    /** 图标 */
    @property (nonatomic, strong) NSString *icon;
    /** 下载量 */
    @property (nonatomic, strong) NSString *download;
    /** 名字 */
    @property (nonatomic, strong) NSString *name;
    
    + (instancetype)appWithDict:(NSDictionary *)dict;
    @end
    
    #import "XDYBApp.h"
    
    @implementation XDYBApp
    + (instancetype)appWithDict:(NSDictionary *)dict
    {
        XDYBApp *app = [[self alloc] init];
        [app setValuesForKeysWithDictionary:dict];
        return app;
    }
    @end
    

    #import "ViewController.h"
    #import "XDYBApp.h"
    
    @interface ViewController ()
    /** 所有数据 */
    @property (nonatomic, strong) NSArray *apps;
    
    /** 内存缓存的图片 */
    @property (nonatomic, strong) NSMutableDictionary *images;
    
    /** 所有的操作对象 */
    @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:[XDYBApp appWithDict:dict]];
            }
            _apps = appArray;
        }
        return _apps;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        
        self.images = nil;
        self.operations = nil;
        [self.queue cancelAllOperations];
    }
    
    #pragma mark - 数据源方法
    - (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];
        
        XDYBApp *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
    

    相关文章

      网友评论

          本文标题:图片缓存

          本文链接:https://www.haomeiwen.com/subject/itulrttx.html