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

第03天多线程网络:(01):多图下载程序缓存处理

2017-04-20 00:00 477 查看
#####一、多图下载程序缓存处理

>>> cell 加载网络图片 新手容易出现两个问题
/*
1.UI很不流畅 (因为放到主线程里面)  ---> 开启子线程下载图片
2.图片被重复下载  ---> 先把之前已经下载的图片保存起来(字典)
内存缓存 ---> 磁盘缓存(保存到沙盒里面)

Document   : 会备份,不允许存放缓存数据(如果存放会直接拒绝上线)
Library    : 两个子目录
Caches      : 缓存数据 (用来保存缓存数据的)
Preferences : 偏好设置 (用来保存一些账号信息)
tmp        : 临时路径(随时会被删除)

*/

>>> 缓存图片获取的逻辑
先去内存缓存中,该图片是否存在,如果存在,那么就直接拿到用,否则去检查磁盘缓存
// 如果有磁盘缓存,那么保存一份到内存,设置图片,否则就直接下载


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;

@end

@implementation ViewController

- (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]];
NSLog(@"字典数组 -- arr %@",arr);
// 字典数组 转成模型数字
// 1.先创建一个空的可变的数组
NSMutableArray *arrM = [NSMutableArray array];

// 2.遍历数组
for (NSDictionary *dict in arr) {
// 3.将模型数据 添加到数组里面
[arrM addObject:[LYHAppModel LYHAppModelWithDict:dict]];
}
// 4.执行完毕 arrM装满了模型
// 将arrM数组 赋值给 dataA (因为 arrM是一个临时的可变数组)
_dataA = arrM;

}
return _dataA;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//    NSLog(@"%@",self.dataA);
}

#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];
// 设置数据
// 2.1 设置标题
cell.textLabel.text = model.name;
// 2.2 设置子标题
cell.detailTextLabel.text = model.download;
// 2.3 设置图标
/*
App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.

http 请求 需要修改plist文件
App Transport
*/
/* !! 这里有两个问题 :
1.UI很不流畅 (因为放到主线程里面)  ---> 开启子线程下载图片
2. 图片被重复下载  ---> 先把之前已经下载的图片保存起来(字典)
*/

//2.4 先去内存缓存中,该图片是否存在,如果存在,那么就直接拿到用,否则去检查磁盘缓存
// 如果有磁盘缓存,那么保存一份到内存,设置图片,否则就直接下载

// 1)没有下载过
// 2)重新打开程序 (先去判断内存缓存有没有,没有再去磁盘缓存里面查找,找到了还需要保存到内存缓存里面)

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

}
else
{

// 2.保存到沙盒缓存
// 2.1 先获取沙盒缓存路径(文件路径)
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
// 2.2 获得图片的名称,不能包含/
NSString *fileName = [model.icon lastPathComponent]; // 获取文件的最后节点
// 2.3 拼接图片的全路径
NSString *fullPath = [caches stringByAppendingPathComponent:fileName];
NSLog(@" fullPath %@",fullPath);

// 检查磁盘缓存(是否存在)
NSData *imageData = [NSData dataWithContentsOfFile:fullPath];
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
{
// 不存在
NSURL *url = [NSURL URLWithString:model.icon];
NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData];
cell.imageView.image = image;
// 1.把图片保存到内存缓存
[self.dict_images setObject:image forKey:model.icon];

// 2.4 写数据到沙盒 (只能拿到imageData 写数据)
/*
参数1 : 写到那个位置
参数2 : 表示原子性
*/
[imageData writeToFile:fullPath atomically:YES];

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

}

/**
参数1 : 目录 (NSCachesDirectory)
参数2 : 在主目录搜索 (NSUserDomainMask)
参数3 : 展开全路径 (YES)
获取的是一个数组 所以我们要获取一个元素
[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]

/Users/liyuhong165/Library/Developer/CoreSimulator/Devices/3123A90B-7532-4EB3-B592-372608850556/data/Containers/Data/Application/3F311BAA-E974-443B-830B-54718DB7C6C1/Library/Caches   这里只是一个文件夹的路径
*/

// NSLog(@"%@",[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] );

// 3.返回cell
return cell;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Objective-C 多线程
相关文章推荐