如何实现从网络获取图片的缓存机制

前言

  在iOS开发中从网络加载图片是一个比较值得思考的问题,因为你要考虑用户的体验,这其实包括流畅度,以及用户的流量考虑,那么今天我就来简单的说点这方面知识。

 

具体实现:

  说到缓存就可以分为内存缓存和沙盒缓存,内存缓存的话就是用简单的用一个字典来记录下载的图片。

  今天的环境就是从网络下载一些图片给tableview的imageView的image赋值,SAMApp是模型类,icon是url.

  1.定义几个属性,具体如下

 

/** 所有数据 */
@property (nonatomic, strong) NSArray *apps;

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

/** 记录正在下载的任务 */
@property (nonatomic, strong) NSMutableDictionary *operations;

/** 队列对象 */
@property (nonatomic, strong) NSOperationQueue *queue;

 

  2.判断内存中有没有值,这里面把url当做key来从字典中取值,相当于内存中取值,如何有值那就直接给imageView的image赋值 

// 从内存中取出图片
    UIImage *image = self.images[app.icon];
    
    if (image) {
        // 内存里面有值
        cell.imageView.image = image;

  

  3.如何内存中没有值,那么就去沙盒中检查有否有需要的图片,这里面把url当作最后的路径目录

// 获取cache目录
        NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory , NSUserDomainMask, YES) firstObject];
        
        // 获取文件名
        NSString *filePath = [app.icon lastPathComponent];
        
        // 计算出全部路径
        NSString *file = [cachePath stringByAppendingString:filePath];
        
        // 加载沙盒中的文件数据
        NSData *data = [NSData dataWithContentsOfFile:file];

  4.如果以上情况都没有,这时应该添加占位视图,如果你是自定义的cell可能不需要,但是系统的UITableViewCell是需要的,要不然需要拖动之后才会显示图片。

  5.这时我们就应该开启线程从网上下载图片,如果只是简单的开启线程下载,这个过程会出现图片的位置不对,搬动刷新之后才正常的状况,这是由于cell的重利用导致的,当图片正在下载的时候,你这个cell可能重利用到下一个位置上去了,然后正好下载结束就会产生错误的图片加载。如何解决呢?

  解决的方法其实很简单,因为我们下载的每一个图片我们都需要去开起一个NSOperation,这时我们用url为key的字典来记录这些正在下载的operation.每次先去这些operation里面取,如果有说明是正在下载,那么就不开起线程,如果没有在开起。

  没有的情况下,说明我们需要开起线程,在这种情况下我们需要注意一种情况,就是如何下载失败的情况下我们就要反这个key从字典里面移除,要不然这一个图片就会不能再下载。

 

核心代码:

 if (image) {
        // 内存里面有值
        cell.imageView.image = image;
    } else {
        //从沙盒里面取
        // 获取cache目录
        NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory , NSUserDomainMask, YES) firstObject];
        
        // 获取文件名
        NSString *filePath = [app.icon lastPathComponent];
        
        // 计算出全部路径
        NSString *file = [cachePath stringByAppendingString:filePath];
        
        // 加载沙盒中的文件数据
        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:@"1"];
            
            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;
            }
        }
        
    }

 

 

  

 

  

 

posted @ 2015-07-11 02:12  samyang1107  阅读(673)  评论(0编辑  收藏  举报