ios多图下载(多线程知识)

一 多图下载实现功能图

多图下载的功能图

二 案例涉及到问题

01 字典转模型
02 图片重复下载—>内存缓存,沙盒缓存处理
03 UI不流畅—>开子线程下载图片(注意线程间通信)
04 图片下载任务被添加到队列中多次—>操作缓存处理
05 图片下载后不显示问题—>主动刷新指定行
06 图片加载中出现数据错乱问题—>设置占位图片
07 在程序开发过程中的一些容错处理

三 针对下载的图片处理思路

/*
 需要解决的问题:
    1> 先检查内存当中有没有图片
    2> 如果有,就直接赋值
    3> 如果没有,就到磁盘中寻找
    4> 如果磁盘中有,就用磁盘中的
    5> 如果磁盘中也没有,那么就缓存,下载
    6> 检查是否有图片正在缓存
    7> 如果有图片缓存,那么相同的图片就不再缓存了
    8> 如果没有图片在缓存,那么就开始缓存图片
 */

四 代码部分

1 模型我这里就不过多的解释了,直接用KVC就能解决
2 主要针对每行cell中的图片处理
2.1 cell内容的前部分
static NSString *ID = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    XFAppItem *item = self.arrayApps[indexPath.row];
    //每行的标题
    cell.textLabel.text = item.name;
    //每行的下载次数
    cell.detailTextLabel.text = item.download;
2.2 检查内存中是否存有已经下载好的图片,有的话就直接用内存的
//先去内存中找
    //检查内存
    UIImage *image = [self.images objectForKey:item.icon];
    if (image) {
        //如果内存中有就用内存的
        cell.imageView.image = image;
    }else{//接后面内存中没有图片的代码
2.3 检查磁盘,看磁盘中是相应的图片
//搜索图片的目录
        NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES)lastObject];

        //得到图片名称
        NSString *fileName = [item.icon lastPathComponent];

        //拼接文件的全路径
        NSString *fullPath = [cachesPath stringByAppendingPathComponent:fileName];

        //如果缓存中没有,在到磁盘中找
        NSData *data = [NSData dataWithContentsOfFile:fullPath];
2.4 如果磁盘中有存有的图片,那么就用磁盘里的,并且将图片保存到内存当中
//如果磁盘中有
        if (data) {
            UIImage *image = [UIImage imageWithData:data];
            //设置cell的图片
            cell.imageView.image = image;
            //将图片存入内存中
            [self.images setObject:image forKey:item.icon];
        }else{//接磁盘中没有图片的代码部分
2.5 尝试着去取下缓存,看是否图片正在缓存,如果正在缓存,那么就不在另外缓存同样的图片了,if语句里面就什么都不做.但是不一定能取到
//检查图片是不是正在下载(尝试着去取一下缓存)
            NSBlockOperation *downloadOperation = [self.operations objectForKey:item.icon];
            //如果正在缓存,那么就什么都不做,让图片缓存
            if (downloadOperation) {

            }else{//接后面的不一定正在缓存
2.6 如果没有相应的图片在缓存,那么就让相应的图片缓存.开启子线程用于缓存下载图片,然后把图片保存到磁盘和内存
//如果没在缓存,就开一个子线程,用于缓存操作
                downloadOperation = [NSBlockOperation blockOperationWithBlock:^{
                    //如果磁盘中没有,再下载

                    //获取图片地址
                    NSURL *url = [NSURL URLWithString:item.icon];
                    //下载图片二进制到本地
                    NSData *data = [NSData dataWithContentsOfURL:url];
                    for (NSInteger i = 0; i < 10000000; i++) {
                    }

                    //转换图片格式
                    UIImage *image = [UIImage imageWithData:data];

                    NSLog(@"1--------%@",[NSThread currentThread]);
                    //把图片保存到内存
                    [self.images setObject:image forKey:item.icon];

                    //把图片保存到磁盘
                    [data writeToFile:fullPath atomically:YES];
2.7 显示图片,这是属于显示UI界面,那么这种操作我们一般都是放到主线程中进行,回到主线程,刷新当前的cell
 //回到主线程,设置图片
                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
//                        cell.imageView.image = image;

                        //刷新指定的cell--->indexPath当前行
                        [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
                        NSLog(@"%@-----------2",[NSThread currentThread]);
                    }];
                }]
2.8 对缓存的一些操作,然后返回一个cell
//添加缓存操作到缓存当中
                [self.operations setObject:downloadOperation forKey:item.icon];

                //添加缓存到队列中
                [self.queue addOperation:downloadOperation];
2.9 最后设置一个图片占位符.理由是因为当网速没有那么快的时候,只显示出来了标题和下载量,并没有图片,那样给用户的感觉不好,所以我们在图片还没有刷新出来之前先设置每一行cell的图片占位符.
代码写在2.5点的代码段上面
//设置一个占位图片
            cell.imageView.image = [UIImage imageNamed:@"/Users/xiaofeng/Desktop/Snip20160316_1.png"];

五 解决的问题(主要问题)

1 UI界面卡顿
2 图片重复下载
3 用户每次滑动都会下载图片—–费流量
4 图片错乱

六 总结

本段代码逻辑很简单,就是可能代码写起来不是很流畅,大家多写几遍就可以了.有什么疑问,可以给我留言,谢谢!!!!
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值