多线程实现多图片下载

本文参考: http://www.jb51.net/article/81614.htm
难点: 如何从网上下载这些图片,下载之后应如何进行存储!
我们一步一步进行解析,先从单线程(主线程)进行多图片下载我们布局上的文字及图片的地址从plist文件中进行读取.
多线程实现多图片下载
文章图片
数据
根据结构,我们自定义一个数据模型文件
DDZApp.h

#import@interface DDZApp : NSObject //图标 @property (nonatomic,strong) NSString *icon; //名字 @property (nonatomic,strong) NSString *name; //下载量 @property (nonatomic,strong) NSString *download; + (instancetype)appWithDict:(NSDictionary *)dict; @end```**DDZApp.m**

import"DDZApp.h" @implementationDDZApp
  • (instancetype)appWithDict:(NSDictionary *)dict {
    DDZApp *app = [[self alloc] init];
    [app setValuesForKeysWithDictionary:dict];
    return app;
}
@end```
以下的都是视图控制器中的代码
ViewController.m
@interface ViewController () //所有数据 @property (nonatomic,strong)NSArray *apps; //内存缓存图片 @property (nonatomic,strong)NSMutableDictionary *imgCache; /**所有操作*/ @property (nonatomic,strong)NSMutableDictionary *operations; /**队列对象*/ @property (nonatomic,strong) NSOperationQueue *queue; @end``` 第一个属性用于存储读取plist文件中的内容,设置为属性保存起来,就可以不用重复读取 第二个属性用于保存从网上下载下来的图片,也是为了不用重复读取 第三个operations使用来存储下载图片的线程操作的字典,主要作用是防止重复下载 第四个queue则是使用多线程时用到的队列

@implementation ViewController
//读取数据
  • (NSArray *)apps {
    if (!_apps) {
    //从plist文件中读取数据
    NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil]];
    NSMutableArray *appArray = [NSMutableArray array];
    for (NSDictionary *dict in dictArray) {
    [appArray addObject:[DDZApp appWithDict:dict]];
    }
    _apps = appArray;
    }
    return _apps;
    }
    //缓存图片
  • (NSMutableDictionary *)imgCache {
    if (!_imgCache) {
    //初始化
    _imgCache = [NSMutableDictionary dictionary];
    }
    return _imgCache;
    }
  • (NSOperationQueue *)queue {
    if (!_queue) {
    _queue = [[NSOperationQueue alloc] init];
    // 最大并发数
    _queue.maxConcurrentOperationCount = 3;
    // 对queue的初始化,以及控制子线程最多为3条
    }
    return _queue;
}```
【多线程实现多图片下载】这两个方法都是为了初始化刚才的两个属性
#pragma mark - 数据源方法 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.apps.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *ID = @"app"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; DDZApp *app = self.apps[indexPath.row]; cell.textLabel.text = app.name; cell.detailTextLabel.text = app.download; //先从内存中取出图片 UIImage *image = self.imgCache[app.icon]; if (image) { cell.imageView.image = image; }else { //内存中没有图片 //将图片文件数据写入到沙盒中 NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]; //获得文件名 NSString *filename = [app.icon lastPathComponent]; //计算出文件的全路径 NSString *file = [cachesPath stringByAppendingPathComponent:filename]; //加载沙盒的文件数据 NSData *data = [NSData dataWithContentsOfFile:file]; //判断沙盒中是否有图片 if (data) { //直接加载沙盒中图片 cell.imageView.image = [UIImage imageWithData:data]; //存到字典(内存)中 self.imgCache[app.icon] = cell.imageView.image; }else { #第一种下载方式 //下载图片 data = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]]; cell.imageView.image = [UIImage imageWithData:data]; //存到内存中 self.imgCache[app.icon] = cell.imageView.image; //将图片数据写入到沙盒中 [data writeToFile:file atomically:YES]; #第二种下载方式 //下载图片 //占位图片 cell.imageView.image = [UIImage imageNamed:@"place.jpg"]; //先判断是否有下载任务 //加载失败后可以重复下载 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.imgCache[app.icon] = image; //回到主线程显示图片 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ //会出现重复占位的问题 //cell.imageView.image = image; //只需找到图片所在的行即可 [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; }]; //将图片数据写入到沙盒中 [data writeToFile:file atomically:YES]; //移除操作 [self.operations removeObjectForKey:app.icon]; }]; //添加到下载队列 [self.queue addOperation:operation]; //添加到字典 self.operations[app.icon] = operation; } } } return cell; }```

    推荐阅读