您的位置:首页 > 理论基础 > 计算机网络

第03天多线程网络:(02):多图下载程序开子线程下载图片

2017-04-20 00:00 465 查看
#####一、多图下载程序开子线程下载图片

>>> 开启子线程刷新UI
NSBlockOperation *downloadOp = [NSBlockOperation blockOperationWithBlock:^{
... 获取图片
.... 线程之间的通信 (UI刷新操作)[刷新tableview每行数据]
}]; // 2.封装操作
// 3.添加操作到队列中
[self.queue addOperation:downloadOp];

>>> tableview不会主动刷新数据(我们手动刷新指定一行的数据)
// [self.tableView reloadData]; 刷新整个tableview
// 刷新某一行
/*
刷新的动画
UITableViewRowAnimationFade,
UITableViewRowAnimationRight,           // slide in from right (or out to right)
UITableViewRowAnimationLeft,
UITableViewRowAnimationTop,
UITableViewRowAnimationBottom,
UITableViewRowAnimationNone,            // available in iOS 3.0
UITableViewRowAnimationMiddle,          // available in iOS 3.2.  attempts to keep cell centered in the space it will/did occupy
UITableViewRowAnimationAutomatic = 100  // available in iOS 5.0.  chooses an appropriate animation style for you
*/
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
>>> 线程之间的通信(非主队列、主队列)
// 线程之间的通信
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
cell.imageView.image = image;
}];


code
LYHAppModel

>>>.h
#import <Foundation/Foundation.h>

@interface LYHAppModel : NSObject

/** app的名称 */
@property(nonatomic, strong) NSString *name;

/** app的图标 */
@property(nonatomic, strong) NSString *icon;

/** app的下载量 */
@property(nonatomic, strong) NSString *download;

// 提供一个方法 用于 字典转模型
+ (instancetype)LYHAppModelWithDict:(NSDictionary *)dict;

@end
>>>.m
#import "LYHAppModel.h"

@implementation LYHAppModel
+ (instancetype)LYHAppModelWithDict:(NSDictionary *)dict
{
LYHAppModel *model = [[LYHAppModel alloc]init];

#pragma  字典转模型 几种方式
#pragma mark 1.一个一个转
//model.name = dict["name"];
#pragma mark 2.KVC
[model setValuesForKeysWithDictionary:dict];

return model;
}
@end

VC

#import "ViewController.h"
#import "LYHAppModel.h"

@interface ViewController ()

/** 数组源 */
// 如何选择使用 可变还是不可变 是根据需求来说的
// 如果数据是固定的 那么就用 不可变的
// 如果数据是不固定 那么就用 可变的

@property(nonatomic, strong) NSArray *dataA;
/** 内存缓存 */
// 每下载完一张图片 要保存起来
@property(nonatomic, strong) NSMutableDictionary *dict_images;

/** 队列(用来下载任务) */
@property(nonatomic, strong)NSOperationQueue *queue;

@end

@implementation ViewController
#pragma mark 懒加载
- (NSOperationQueue *)queue
{
if (_queue == nil) {
_queue = [[NSOperationQueue alloc]init];
// 在程序里面 最好只开3~5个队列
// 设置队列并发数
_queue.maxConcurrentOperationCount = 5;
}
return  _queue;
}

- (NSMutableDictionary *)dict_images
{
if (_dict_images == nil) {
_dict_images = [NSMutableDictionary dictionary];
}
return _dict_images;
}

- (NSArray *)dataA
{
if (_dataA == nil) {

// 字典数组
NSArray *arr = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil]];
NSMutableArray *arrM = [NSMutableArray array];
for (NSDictionary *dict in arr) {
[arrM addObject:[LYHAppModel LYHAppModelWithDict:dict]];
}
_dataA = arrM;

}
return _dataA;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}

#pragma mark --- ---
#pragma mark tableViewDataScoure
// 多少组
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}

// 多少行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataA.count;
}

// cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.创建cell
static NSString *ID = @"app";
// 2.设置cell数据
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 拿到该行cell的数据
LYHAppModel *model = [self.dataA objectAtIndex:indexPath.row];
// 设置数据

cell.textLabel.text = model.name;
cell.detailTextLabel.text = model.download;

//2.4 先去内存缓存中,该图片是否存在,如果存在,那么就直接拿到用,否则去检查磁盘缓存
// 如果有磁盘缓存,那么保存一份到内存,设置图片,否则就直接下载
// 1)没有下载过
// 2)重新打开程序 (先去判断内存缓存有没有,没有再去磁盘缓存里面查找,找到了还需要保存到内存缓存里面)

UIImage *image = [self.dict_images objectForKey:model.icon];
if (image) {
cell.imageView.image = image;
NSLog(@"--%zd的图片使用内存缓存图片",indexPath.row);

}
else
{

NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *fileName = [model.icon lastPathComponent]; // 获取文件的最后节点
NSString *fullPath = [caches stringByAppendingPathComponent:fileName];
//NSLog(@" fullPath %@",fullPath);

// 检查磁盘缓存(是否存在)
NSData *imageData = [NSData dataWithContentsOfFile:fullPath];
// 废除磁盘缓存
imageData = nil;
if (imageData)
{
UIImage *image = [UIImage imageWithData:imageData];
cell.imageView.image = image;
NSLog(@"--%zd的图片使用磁盘缓存图片",indexPath.row);

// 1.把图片保存到内存缓存
[self.dict_images setObject:image forKey:model.icon];
}
else
{
// 不存在

//            NSOperationQueue *queue = [[NSOperationQueue alloc]init]; // 1.非主队列
NSBlockOperation *downloadOp = [NSBlockOperation blockOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:model.icon];
NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData];
//                NSLog(@"---download --%@",[NSThread currentThread]);

#pragma UI刷新的操作
// 演示网速慢的情况
[NSThread sleepForTimeInterval:2.0];

// 线程之间的通信
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
// [self.tableView reloadData]; 刷新整个tableview
// 刷新某一行
/*
刷新的动画
UITableViewRowAnimationFade,
UITableViewRowAnimationRight,           // slide in from right (or out to right)
UITableViewRowAnimationLeft,
UITableViewRowAnimationTop,
UITableViewRowAnimationBottom,
UITableViewRowAnimationNone,            // available in iOS 3.0
UITableViewRowAnimationMiddle,          // available in iOS 3.2.  attempts to keep cell centered in the space it will/did occupy
UITableViewRowAnimationAutomatic = 100  // available in iOS 5.0.  chooses an appropriate animation style for you
*/
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
cell.imageView.image = image;
//                    NSLog(@"---UI --%@",[NSThread currentThread]);
}];

// 1.把图片保存到内存缓存
[self.dict_images setObject:image forKey:model.icon];
/*
参数1 : 写到那个位置
参数2 : 表示原子性
*/
[imageData writeToFile:fullPath atomically:YES];

NSLog(@"%zd---下载-- ",indexPath.row);
}]; // 2.封装操作

// 3.添加操作到队列中
[self.queue addOperation:downloadOp];

}

}

return cell;
}

/*
1.UI很不流畅 (因为放到主线程里面)  ---> 开启子线程下载图片
2.图片被重复下载  ---> 先把之前已经下载的图片保存起来(字典)
内存缓存 ---> 磁盘缓存(保存到沙盒里面)
3.图片不会刷新(解决)
4.图片重复下载
5.数据错乱
*/

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Objective-C 多线程