博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何实现从网络获取图片的缓存机制
阅读量:5337 次
发布时间:2019-06-15

本文共 4058 字,大约阅读时间需要 13 分钟。

前言

  在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;            }        }            }

 

 

  

 

  

 

转载于:https://www.cnblogs.com/samyangldora/p/4637833.html

你可能感兴趣的文章
String比较
查看>>
Django之Models
查看>>
CSS 透明度级别 及 背景透明
查看>>
Linux 的 date 日期的使用
查看>>
PHP zip压缩文件及解压
查看>>
SOAP web service用AFNetWorking实现请求
查看>>
Java变量类型,实例变量 与局部变量 静态变量
查看>>
mysql操作命令梳理(4)-中文乱码问题
查看>>
Python环境搭建(安装、验证与卸载)
查看>>
一个.NET通用JSON解析/构建类的实现(c#)
查看>>
Windows Phone开发(5):室内装修 转:http://blog.csdn.net/tcjiaan/article/details/7269014
查看>>
详谈js面向对象 javascript oop,持续更新
查看>>
关于这次软件以及pda终端的培训
查看>>
jQuery上传插件Uploadify 3.2在.NET下的详细例子
查看>>
如何辨别一个程序员的水平高低?是靠发量吗?
查看>>
新手村之循环!循环!循环!
查看>>
正则表达式的用法
查看>>
线程安全问题
查看>>
SSM集成activiti6.0错误集锦(一)
查看>>
下拉刷新
查看>>