開發(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ù)流程圖,下載過程就更為清晰明了。

移動開發(fā)培訓,Android培訓,安卓培訓,手機開發(fā)培訓,手機維修培訓,手機軟件培訓

根據(jù)流程圖一些坑,我們就可以完美的避免掉了。這樣寫程序也更有章法。

2 - 開始下載圖片

根據(jù)前面的介紹,我們需要有兩個緩存對象:

  1. 圖片data的內存緩存

  2. 下載隊列的緩存

我們可以使用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