開發(fā)中非常常用的就是就是圖片下載,我們常用的就是SDWebImage,但是作為開發(fā)人員,不僅要能會用,還要知道其原理。本文就會介紹多圖下載的實現(xiàn)。
本文中的示例Demno地址,下載后項目位于iOS_Demo/09-多圖片多線程下載
1 - 問題
開篇我就先將多圖下載過程中出現(xiàn)的問題擺出來,讓我們能夠一一克服
。
1:下載過程要放到子線程中,否則會導致UI線程卡頓
2:圖片會重復下載,我們不僅要把下載完的圖片放到內存中,還要把下載隊列也緩存起來,否則可能圖片沒有下載完,會多次創(chuàng)建下載隊列
3:沙盒緩存,放到哪里,根據(jù)下面對沙盒文件的介紹我們需要把圖片放到Library/Caches目錄下。
Document : iTunes會備份Library : 1:Caches:緩存文件,不會清除 2:Preferences:偏好設置,保存賬號信息 tmp :臨時路徑,隨時會被刪除,臨時的不是重要的數(shù)據(jù)
下載流程圖
明白了問題后,我們需要制定戰(zhàn)略(畫流程圖),這樣根據(jù)流程圖,下載過程就更為清晰明了。
根據(jù)流程圖一些坑,我們就可以完美的避免掉了。這樣寫程序也更有章法。
2 - 開始下載圖片
根據(jù)前面的介紹,我們需要有兩個緩存對象:
圖片data的內存緩存
下載隊列的緩存
我們可以使用NSMutableDictionary進行緩存,
這里我們假設兩個緩存對象分別是:
/** 內存中圖片的緩存字典 */@property (nonatomic,strong)NSMutableDictionary * memoryImages; /** 下載操作的字典 */@property (nonatomic,strong)NSMutableDictionary * operations;
2.1 內存緩存中取值
所以下載前,我們先要到內存中取值
NSData *imageData = [self.memoryImages objectForKey:url];
如果imageData
對象存在,我們就直接設置到Cell上。
2.2 內存緩存中沒有,我們到沙盒中取值
內存緩存中不存在時我們到沙盒中進行查看:
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject; //獲取圖片名字,圖片名稱不能包含URL, NSString *fileName = [url lastPathComponent]; NSString *filePaPath = [path stringByAppendingPathComponent:fileName]; //內存中沒有圖片的緩存 -- 從沙盒中取出 NSData *imageData = [NSData dataWithContentsOfFile:filePaPath];
如果圖片存在,我們需要把圖片設置到Cell上,并且放一份到內存緩存中
//沙盒中取出后,放一份到內存緩存中[self.memoryImages setObject:imageData forKey:url];
這樣下次就不用頻繁訪問沙盒了。
2.2 內存緩存中沒有,沙盒中也沒有,我們需要判斷下載隊列是否已經存在
如果網(wǎng)速慢一些,并且Cell上下滑動的頻率快一些的話,假如第一次第5行的Cell顯示的時候,內存緩存中沒有,沙盒中也沒有,這時我們創(chuàng)建了下載對象,然后這行Cell被滑出屏幕,再次進來的時候圖片還是沒有下載完畢,經過判斷內存緩存中沒有,沙盒中也沒有,我們如果再次創(chuàng)建下載對象的話,就會重復下載圖片了,所以我們要把下載隊列也進行緩存,當內存緩存中沒有,沙盒中也沒有時,我們先判斷下載隊列中是否已經存在了。
這里使用的是NSBlockOperation
NSBlockOperation *doo = [self.operations objectForKey:url];
2.2 內存緩存中沒有,沙盒中也沒有,下載隊列也沒有
這時我們就需要創(chuàng)建下載對象進行下載了。
首先我們先可以設置一個占位圖,這樣的顯示更為友好一下。
NSBlockOperation *downO = [NSBlockOperation blockOperationWithBlock:^{ NSURL *uurl = [NSURL URLWithString:url]; NSURLSession *session = [NSURLSession sharedSession]; NSURLSessionDataTask *down = [session dataTaskWithURL:uurl completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { //圖片的下載過程 }]; [down resume]; }];
同時加入下載隊列
//下載對象加入隊列中 [self.operations setObject:downO forKey:url]; [self.queue addOperation:downO];
圖片下載完畢后,我們需要
//把圖片data存入內存中[self.memoryImages setObject:data forKey:url];//同時寫入沙盒中,永久緩存[data writeToFile:filePaPath atomically:YES];
同時在主線程中更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{ UIImage *image = [UIImage imageWithData:data]; cell.iconView.image = image; [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; }];
這樣完整的圖片下載過程就好了。
http://www.cnblogs.com/fengtengfei/p/6714745.html