iOS多线程实现多图下载功能

本文实例为大家分享了iOS多线程实现多图下载功能的具体代码,供大家参考,具体内容如下

一.模型文件代码如下

// XMGAPP.h 

#import <Foundation/Foundation.h> 

@interface XMGAPP : NSObject 

/** APP的名称 */
@property (nonatomic, strong) NSString *name;
/** APP的图片的url地址 */
@property (nonatomic, strong) NSString *icon;
/** APP的下载量 */
@property (nonatomic, strong) NSString *download; 

+(instancetype)appWithDict:(NSDictionary *)dict;
@end
// XMGAPP.m 

#import "XMGAPP.h" 

@implementation XMGAPP 

+(instancetype)appWithDict:(NSDictionary *)dict
{
  XMGAPP *appM = [[XMGAPP alloc]init];
  //KVC
  [appM setValuesForKeysWithDictionary:dict]; 

  return appM;
}
@end

控制器.m代码如下:

// ViewController.m 

#import "ViewController.h"
#import "XMGAPP.h" 

@interface ViewController ()
/** tableView的数据源 */
@property (nonatomic, strong) NSArray *apps;
/** 内存缓存 */
@property (nonatomic, strong) NSMutableDictionary *images;
/** 队列 */
@property (nonatomic, strong) NSOperationQueue *queue;
/** 操作缓存 */
@property (nonatomic, strong) NSMutableDictionary *operations;
@end 

@implementation ViewController 

#pragma mark ----------------------
#pragma mark lazy loading
-(NSOperationQueue *)queue
{
  if (_queue == nil) {
    _queue = [[NSOperationQueue alloc]init];
    //设置最大并发数
    _queue.maxConcurrentOperationCount = 5;
  }
  return _queue;
}
-(NSMutableDictionary *)images
{
  if (_images == nil) {
    _images = [NSMutableDictionary dictionary];
  }
  return _images;
}
-(NSArray *)apps
{
  if (_apps == nil) { 

    //字典数组
    NSArray *arrayM = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil]]; 

    //字典数组---->模型数组
    NSMutableArray *arrM = [NSMutableArray array];
    for (NSDictionary *dict in arrayM) {
      [arrM addObject:[XMGAPP appWithDict:dict]];
    }
    _apps = arrM;
  }
  return _apps;
} 

-(NSMutableDictionary *)operations
{
  if (_operations == nil) {
    _operations = [NSMutableDictionary dictionary];
  }
  return _operations;
} 

#pragma mark ----------------------
#pragma mark UITableViewDatasource
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
  return 1;
} 

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
  return self.apps.count;
} 

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  static NSString *ID = @"app"; 

  //1.创建cell
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 

  //2.设置cell的数据
  //2.1 拿到该行cell对应的数据
  XMGAPP *appM = self.apps[indexPath.row]; 

  //2.2 设置标题
  cell.textLabel.text = appM.name; 

  //2.3 设置子标题
  cell.detailTextLabel.text = appM.download; 

  //2.4 设置图标 

  //先去查看内存缓存中该图片时候已经存在,如果存在那么久直接拿来用,否则去检查磁盘缓存
  //如果有磁盘缓存,那么保存一份到内存,设置图片,否则就直接下载
  //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];
      } 

    }
  } 

  //3.返回cell
  return cell;
} 

-(void)didReceiveMemoryWarning
{
  [self.images removeAllObjects]; 

  //取消队列中所有的操作
  [self.queue cancelAllOperations];
} 

//1.UI很不流畅 --- > 开子线程下载图片
//2.图片重复下载 ---> 先把之前已经下载的图片保存起来(字典)
//内存缓存--->磁盘缓存 

//3.图片不会刷新--->刷新某行
//4.图片重复下载(图片下载需要时间,当图片还未完全下载之前,又要重新显示该图片)
//5.数据错乱 ---设置占位图片 

/*
 Documents:会备份,不允许
 Libray
  Preferences:偏好设置 保存账号
  caches:缓存文件
 tmp:临时路径(随时会被删除)
 */ 

@end 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • IOS多线程实现多图片下载(二)

    上篇文章给大家介绍了IOS多线程实现多图片下载1,本文继续给大家介绍ios多线程下载图片. 这次是用多线程进行图片的下载与存储,而且考虑到下载失败,占位图片的问题(第一张就是下载失败的图片) 闲话少说,上代码吧,因为有一部分和上次的一样,所以这里只上传不一样的 先给大家展示下效果图: 依旧都是在ViewController.m中 1. @interface ViewController () //所有数据 @property (nonatomic,strong)NSArray *apps; //

  • iOS开发网络篇—实现大文件的多线程断点下载

    说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时开启多条线程下载一个较大的文件.因为实现过程较为复杂,所以下面贴出完整的代码. 实现思路:下载开始,创建一个和要下载的文件大小相同的文件(如果要下载的文件为100M,那么就在沙盒中创建一个100M的文件,然后计算每一段的下载量,开启多条线程下载各段的数据,分别写入对应的文件部分). 项目中用到的主要类如下: 完成的实现代码如下: 主控制器中的代码: #import "YYViewController.h" #import

  • IOS多线程实现多图片下载(一)

    在没有步入正文之前先给大家展示下效果图,如果大家觉得很满意请继续往下阅读全文. 大家可以看到这个界面很简单,其实就是UITableView的布局,但是难点是在于如何从网上下载这些图片,下载之后应如何进行存储! 我们一步一步进行解析,先从单线程(主线程)进行多图片下载我们布局上的文字及图片的地址从plist文件中进行读取 根据结构,我们自定义一个数据模型文件 DDZApp.h #import <Foundation/Foundation.h> @interface DDZApp : NSObje

  • iOS多线程实现多图下载功能

    本文实例为大家分享了iOS多线程实现多图下载功能的具体代码,供大家参考,具体内容如下 一.模型文件代码如下 // XMGAPP.h #import <Foundation/Foundation.h> @interface XMGAPP : NSObject /** APP的名称 */ @property (nonatomic, strong) NSString *name; /** APP的图片的url地址 */ @property (nonatomic, strong) NSString *

  • iOS评分(评价)星星图打分功能

    下载地址:https://github.com/littleSunZheng/StarGradeView 起因:项目中往往涉及到用户的评分反馈,在我的"E中医"项目中,涉及到几处.对此我参考了美团和滴滴的评分图. 评分视图分为展示和评分两种: (1)多数情况下"评分功能"是要简介易用的.那种 星星准确显示百分比(分数)的功能反而不好用,这种多数用在显示评分上,不需要用户去点击,因为用户想评价"9.8分",手指头是不能准确点击的.但是显示的时候你根

  • C# 文件上传下载(Excel导入,多线程下载)功能的实现代码

    废话不多说了,直接给大家贴代码,具体代码如下所示: //打开Excel文件,转换为DataTable DataTable dtExcel; private void OpenFile() { OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "Microsoft Excel files(*.xls)|*.xls;*.xlsx"; //筛选打开文件类型 :图片 *.jpg|*.jpg|*.bmp|*.bmp ;&q

  • Android多线程+单线程+断点续传+进度条显示下载功能

    效果图 白话分析: 多线程:肯定是多个线程咯 断点:线程停止下载的位置 续传:线程从停止下载的位置上继续下载,直到完成任务为止. 核心分析: 断点: 当前线程已经下载的数据长度 续传: 向服务器请求上次线程停止下载位置的数据 con.setRequestProperty("Range", "bytes=" + start + "-" + end); 分配线程: int currentPartSize = fileSize / mThreadNum

  • jQuery实现经典的网页3D轮播图封装功能【附源码下载】

    本文实例讲述了jQuery实现的网页3D轮播图封装功能.分享给大家供大家参考,具体如下: 网页伪3D轮播图,其实就是轮播图旋转木马效果.其实在jquery插件库也有很多旋转木马的插件,但是博主封装的这个新的插件比起以上的都适应性更好.其适应性好表现在:调用灵活性高用法更简单,css样式都封装好了基本不用写,在body里面写ul>li>img标签即可,可设置参数多,甚至不同图片的大小都可以自适应轮播,各个浏览器兼容性好(包括IE,虽然我没测过IE8以下浏览器,不过IE8以上都没问题),好了,以下

  • iOS多线程介绍

    一.前言部分 最近在面试,重新温习了一遍多线程,希望加深一遍对于多线程的理解. 1.什么是进程? 1).要了解线程我们必须先了解进程,通俗来讲进程就是在系统中运行的一个应用程序. 2).每个线程之间是独立存在的,分别运行在其专用的且受保护的内存空间中. 3).比如打开QQ或Xcode系统会分别开启两个进程 如图: 4).我们可以通过"活动监视器"查看Mac系统中所开启的进程. 2.什么是线程? 1).一个进程要想执行任务必须得有线程,即一个进程至少要有一个线程. 2).线程是进程的基本

  • iOS高仿微信表情输入功能代码分享

    最近项目需求,要实现一个类似微信的的表情输入,于是把微信的表情扒拉出来,实现了一把.可以从这里下载源码.看起来表情输入没有多少东西,不外乎就是用NSTextAttachment来实现图文混排,结果在实现的过程中遇到了很多小问题,接下来会一一介绍遇到过的坑.先上一张效果图: 一.实现表情选择View(WKExpressionView) 具体的实现就不细说了,主要功能就是点击表情时,将对应表情的图片名称通知给delegate. 二.实现表情textView(WKExpressionTextView)

  • 利用iOS实现系统相册大图浏览功能详解

    前言 本文主要给大家介绍了关于iOS实现系统相册大图浏览功能的相关资料,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 最终效果图 大图浏览 实现过程 创建两个UICollectionView分别放置大图和缩略图 实现大图和缩略图的联动 实现当前展示的大图对应的缩略图放大效果 实现原理 创建collectionView非常简单,只要正常创建就好,值得注意的是:由于需要当前展示的图片的缩略图始终保持在屏幕中间位置,所以在创建缩略图的collectionView的时候需要对coll

随机推荐