美文网首页iOS碎碎念
关于table中cell的缓存策略

关于table中cell的缓存策略

作者: tiGress | 来源:发表于2017-07-26 09:32 被阅读15次

    1.模型层中提供一个图片的URL,如果不加以缓存,每次都会重新下载,造成界面卡顿。缓存思路如下:

    方法一:不使用三方,自己手动代码实现。

    1.使用NSMutableDictionary 创建一个对象。将图片保存在里面。每次加载cell的时候,先尝试去dic中去取,取到了用dic中的图片,不需要下载,取不到,需要网上下载,然后保存图片到dic中。

         问题:项目退出后dic即销毁。每次重新启动就要下载图片。

    解决办法:配合nscaches 磁盘缓存机制。

    1.先查看内存缓存中是否存在。

          存在,直接加载。

          不存在,检查磁盘缓存,

                        磁盘缓存,存在,加载磁盘缓存的,并且添加到内存中。

                       磁盘缓存也不存在。下载网络资源,保存到内存中,保存到磁盘中。

    简单的代码如上。不过要把下载的代码放到子线程中。

    继续完善

    创建子线程后,发现了一些问题。

    1.图片不会刷新--->刷新某行

    2.图片重复下载(图片下载需要时间,当图片还未完全下载之前,又要重新显示该图片)

    3.数据错乱 ---设置占位图片

    修改思路:对于第二个问题,将下载队列添加到内存中,下载之前先判断有没有该图片的下载队列,有的话,就等一下,没有的话才进行下载操作。数据错乱的原因,是cell的重用,然后URL错误没有获取到图片。所以在下载的时候,先清空cell中的图片数据。

    //先去查看内存缓存中该图片时候已经存在,如果存在那么久直接拿来用,否则去检查磁盘缓存

    //如果有磁盘缓存,那么保存一份到内存,设置图片,否则就直接下载

    //1)没有下载过

    //2)重新打开程序

    UIImage *image = [self.images objectForKey:appM.icon];

    if (image) {

    cell.imageView.image = image;

    NSLog(@"%zd处的图片使用了内存缓存中的图片",indexPath.row) ;

    }else

    {

    //保存图片到沙盒缓存

    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

    //获得图片的名称,不能包含/

    NSString *fileName = [appM.icon lastPathComponent];

    //拼接图片的全路径

    NSString *fullPath = [caches stringByAppendingPathComponent:fileName];

    //检查磁盘缓存

    NSData *imageData = [NSData dataWithContentsOfFile:fullPath];

    //废除

    imageData = nil;

    if (imageData) {

    UIImage *image = [UIImage imageWithData:imageData];

    cell.imageView.image = image;

    NSLog(@"%zd处的图片使用了磁盘缓存中的图片",indexPath.row) ;

    //把图片保存到内存缓存

    [self.images setObject:image forKey:appM.icon];

    //            NSLog(@"%@",fullPath);

    }else

    {

    //检查该图片时候正在下载,如果是那么久什么都捕捉,否则再添加下载任务

    NSBlockOperation *download = [self.operations objectForKey:appM.icon];

    if (download) {

    }else

    {

    //先清空cell原来的图片

    cell.imageView.image = [UIImage imageNamed:@"Snip20160221_306"];

    download = [NSBlockOperation blockOperationWithBlock:^{

    NSURL *url = [NSURL URLWithString:appM.icon];

    NSData *imageData = [NSData dataWithContentsOfURL:url];

    UIImage *image = [UIImage imageWithData:imageData];

    NSLog(@"%zd--下载---",indexPath.row);

    //容错处理

    if (image == nil) {

    [self.operations removeObjectForKey:appM.icon];

    return ;

    }

    //演示网速慢的情况

    //[NSThread sleepForTimeInterval:3.0];

    //把图片保存到内存缓存

    [self.images setObject:image forKey:appM.icon];

    //NSLog(@"Download---%@",[NSThread currentThread]);

    //线程间通信

    [[NSOperationQueue mainQueue] addOperationWithBlock:^{

    //cell.imageView.image = image;

    //刷新一行

    [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];

    //NSLog(@"UI---%@",[NSThread currentThread]);

    }];

    //写数据到沙盒

    [imageData writeToFile:fullPath atomically:YES];

    //移除图片的下载操作

    [self.operations removeObjectForKey:appM.icon];

    }];

    //添加操作到操作缓存中

    [self.operations setObject:download forKey:appM.icon];

    //添加操作到队列中

    [self.queue addOperation:download];

    }

    }

    }

    注意:多图下载容易产生内存警告问题。对于不使用sdwebimage的时候,还要注意添加如下代码:

    -(void)didReceiveMemoryWarning

    {

    [self.imagesremoveAllObjects];

    //取消队列中所有的操作

    [self.queuecancelAllOperations];

    }

    当然使用 sdwebimage 可以一行代码搞定所有的。

    相关文章

      网友评论

        本文标题:关于table中cell的缓存策略

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