1.模型層中提供一個圖片的URL,如果不加以緩存,每次都會重新下載,造成界面卡頓。緩存思路如下:
方法一:不使用三方,自己手動代碼實現(xiàn)。
1.使用NSMutableDictionary 創(chuàng)建一個對象。將圖片保存在里面。每次加載cell的時候,先嘗試去dic中去取,取到了用dic中的圖片,不需要下載,取不到,需要網(wǎng)上下載,然后保存圖片到dic中。
? ? ?問題:項目退出后dic即銷毀。每次重新啟動就要下載圖片。
解決辦法:配合nscaches 磁盤緩存機制。
1.先查看內(nèi)存緩存中是否存在。
? ? ? 存在,直接加載。
? ? ? 不存在,檢查磁盤緩存,
? ? ? ? ? ? ? ? ? ? 磁盤緩存,存在,加載磁盤緩存的,并且添加到內(nèi)存中。
? ? ? ? ? ? ? ? ? ?磁盤緩存也不存在。下載網(wǎng)絡(luò)資源,保存到內(nèi)存中,保存到磁盤中。
簡單的代碼如上。不過要把下載的代碼放到子線程中。
繼續(xù)完善
創(chuàng)建子線程后,發(fā)現(xiàn)了一些問題。
1.圖片不會刷新--->刷新某行
2.圖片重復下載(圖片下載需要時間,當圖片還未完全下載之前,又要重新顯示該圖片)
3.數(shù)據(jù)錯亂 ---設(shè)置占位圖片
修改思路:對于第二個問題,將下載隊列添加到內(nèi)存中,下載之前先判斷有沒有該圖片的下載隊列,有的話,就等一下,沒有的話才進行下載操作。數(shù)據(jù)錯亂的原因,是cell的重用,然后URL錯誤沒有獲取到圖片。所以在下載的時候,先清空cell中的圖片數(shù)據(jù)。
//先去查看內(nèi)存緩存中該圖片時候已經(jīng)存在,如果存在那么久直接拿來用,否則去檢查磁盤緩存
//如果有磁盤緩存,那么保存一份到內(nèi)存,設(shè)置圖片,否則就直接下載
//1)沒有下載過
//2)重新打開程序
UIImage *image = [self.images objectForKey:appM.icon];
if (image) {
cell.imageView.image = image;
NSLog(@"%zd處的圖片使用了內(nèi)存緩存中的圖片",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) ;
//把圖片保存到內(nèi)存緩存
[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 ;
}
//演示網(wǎng)速慢的情況
//[NSThread sleepForTimeInterval:3.0];
//把圖片保存到內(nèi)存緩存
[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]);
}];
//寫數(shù)據(jù)到沙盒
[imageData writeToFile:fullPath atomically:YES];
//移除圖片的下載操作
[self.operations removeObjectForKey:appM.icon];
}];
//添加操作到操作緩存中
[self.operations setObject:download forKey:appM.icon];
//添加操作到隊列中
[self.queue addOperation:download];
}
}
}
注意:多圖下載容易產(chǎn)生內(nèi)存警告問題。對于不使用sdwebimage的時候,還要注意添加如下代碼:
-(void)didReceiveMemoryWarning
{
[self.imagesremoveAllObjects];
//取消隊列中所有的操作
[self.queuecancelAllOperations];
}
當然使用 sdwebimage 可以一行代碼搞定所有的。