多圖片下載 之 SDWebImage

首先先了解一下我們多圖片下載的一般解決方案

注:以下模擬AppStore瀏覽購買項目場景

主體思路

主體思路

場景還原:

進入app,當圖片還沒顯示完成時,我們不停的拖拽tableview,就會不停的調用 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath. 導致以下倆個問題.

出現(xiàn)問題:

  1. 重復下載操作
  2. cell重用導致圖片錯位
    第一次進入app我們會進行下載圖片,由于下載圖片是一個耗時操作,此時用戶進行拖拽,由于cell的重用機制移出屏幕的cell會被重用,之前的cell會被重用到下方,恰巧圖片又剛好下載完成,這時候如果我們任然進行顯示
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    cell.imageView.image = image;
 }];

就會出現(xiàn) --- 植物大戰(zhàn)僵尸2 捕魚 都出現(xiàn)了錯亂

cell重用導致錯亂

解決辦法:

1.為了防止圖片下載操作重復,我們將對應的操作對象做記錄,無論是成功還是失敗最后我們都移除該對象,保證操作的唯一性.

/** 內存緩存的圖片 */
@property (nonatomic, strong) NSMutableDictionary *images;

/** 所有的操作對象 */
@property (nonatomic, strong) NSMutableDictionary *operations;

2.下載完成我們去刷新對應的cell

// 回到主線程顯示圖片
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
     [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}];

整體實現(xiàn)代碼

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *ID = @"app";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    XMGApp *app = self.apps[indexPath.row];
    cell.textLabel.text = app.name;
    cell.detailTextLabel.text = app.download;

    // 先從內存緩存中取出圖片
    UIImage *image = self.images[app.icon];
    if (image) { // 內存中有圖片,顯示圖片
        cell.imageView.image = image;
    } else {  // 內存中沒有圖片,檢查沙盒中是否有圖片

        // 獲得Library/Caches文件夾
        NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
        // 獲得文件名
        NSString *filename = [app.icon lastPathComponent];
        // 計算出文件的全路徑
        NSString *file = [cachesPath stringByAppendingPathComponent:filename];
        // 加載沙盒的文件數(shù)據(jù)
        NSData *data = [NSData dataWithContentsOfFile:file];

        if (data) { // 沙盒中有圖片,直接利用沙盒中圖片
            UIImage *image = [UIImage imageWithData:data];
            cell.imageView.image = image;
            // 存到字典中
            self.images[app.icon] = image;
        } else { // 沙盒中沒有圖片,下載圖片
            cell.imageView.image = [UIImage imageNamed:@"placeholder"];

            //查詢是否有下載任務
            NSOperation *operation = self.operations[app.icon];
            if (operation == nil) { // 這張圖片暫時沒有下載任務
                operation = [NSBlockOperation blockOperationWithBlock:^{
                    // 下載圖片
                    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]];
                    // 數(shù)據(jù)加載失敗
                    if (data == nil) {
                        // 移除操作
                        [self.operations removeObjectForKey:app.icon];
                        return;
                    }

                    UIImage *image = [UIImage imageWithData:data];

                    // 存到字典中
                    self.images[app.icon] = image;

                    // 回到主線程顯示圖片
                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                        [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
                    }];

                    // 將圖片文件數(shù)據(jù)寫入沙盒中
                    [data writeToFile:file atomically:YES];
                    // 移除操作
                    [self.operations removeObjectForKey:app.icon];
                }];

                // 添加到隊列中
                [self.queue addOperation:operation];

                // 存放到字典中
                self.operations[app.icon] = operation;
            }
        }
    }

    return cell;
}


小結:由于自己去完成多圖片的下載 細節(jié)比較多,需要考慮cell重用錯亂,重復下任務,網絡錯誤data為空等等一系列的細節(jié)問題,為了提高開發(fā)效率我們通常會使用第三方框架


最終解決方案

第三方框架 SDWebImage

  • 導入頭文件
#import "UIImageView+WebCache.h"
  • 加載圖片設置占位圖
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:app.icon] placeholderImage:[UIImage imageNamed:@"placeholder"]];

對照

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *ID = @"app";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    XMGApp *app = self.apps[indexPath.row];
    cell.textLabel.text = app.name;
    cell.detailTextLabel.text = app.download;

    //只需要一句話
    [cell.imageView sd_setImageWithURL:[NSURL URLWithString:app.icon] placeholderImage:[UIImage imageNamed:@"placeholder"]];

    return cell;
}

而且它也幫我們完成了緩存的處理

緩存圖片

讓我們簡單的了解一下如何使用這個強大的第三方框架

1.下面我們以參數(shù)較多的方法舉例:

 [cell.imageView sd_setImageWithURL:[NSURL URLWithString:app.icon] placeholderImage:[UIImage imageNamed:@"placeholder"] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {
        // expectedSize: 圖片的總字節(jié)數(shù)
        // receivedSize: 已經接收的圖片字節(jié)數(shù)

        NSLog(@"下載進度:%f", (double)receivedSize / expectedSize);
    } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
        NSLog(@"下載完圖片");
    }];

1社牲,sd_setImageWithURL獲取網絡圖片
2悴了,placeholderImage占位圖片
3熟空,progress 下載進度 用法: NSLog(@"下載進步:%f",(double)receivedSize / expectedSize);
4, *image *error *imageURL分別完成后返回 的圖片巡揍,錯誤和下載地址
5腮敌,SDImageCacheType cacheType 是枚舉類型糜工,圖片存儲位置在內存捌木、磁盤或無
6,SDWebImageOptions 枚舉類型
    用法:SDWebImageOptions options = SDWebImageRetryFailed | SDWebImageLowPriority
    SDWebImageRetryFailed 下載失敗重復下載        常用
    SDWebImageLowPriority 當UI交互的時候暫停下載   常用
    SDWebImageCacheMemoryOnly 只存圖片在內存
    SDWebImageProgressiveDownload 可以像瀏覽器那樣從上往下下載刷新圖片
    SDWebImageRefreshCached 刷新緩存
    SDWebImageHighPriority  高優(yōu)先級
    SDWebImageDelayPlaceholder 不加載占位圖

options參數(shù)圖片

options參數(shù)圖片

2.內存處理

因為SDWebImgae是屬于整個項目彬檀,不是屬于某個控制器窍帝,所以不要在控制器里的didReceiveMemoryWarning處理內存問題坤学,而且在AppDelegate.m添加applicationDidReceiveMemoryWarning方法

  • AppDelegate中 (√)
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
    // 取消所有下載
    [[SDWebImageManager sharedManager] cancelAll];
    // 清除內存緩存
    [[SDWebImageManager sharedManager].imageCache clearMemory];
}
  • 當前控制器中 出現(xiàn)內存警告(×)
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    self.images = nil;
    self.operations = nil;
    [self.queue cancelAllOperations];
}

3.其他功能

  • SDWebImage的圖片緩存周期是多長:1個星期
默認緩存周期1周
//設置100天深浮,默認是7天
[SDWebImageManager sharedManager].imageCache.maxCacheAge = 100 * 24 * 60 * 60
  • SDWebImage的圖片最大尺寸(字節(jié))
圖片最大尺寸(字節(jié))
//無默認值飞苇,單位字節(jié)
[SDWebImageManager sharedManager].imageCache.maxCacheSize = ;

拓展:只下載圖片不設置 --- 給Button設置圖片時可以使用

[[SDWebImageManager sharedManager] downloadImageWithURL:<#(NSURL *)#> options:<#(SDWebImageOptions)#> progress:^(NSInteger receivedSize, NSInteger expectedSize) {

    } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {

    }]
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市羽利,隨后出現(xiàn)的幾起案子这弧,更是在濱河造成了極大的恐慌匾浪,老刑警劉巖蛋辈,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冷溶,死亡現(xiàn)場離奇詭異逞频,居然都是意外死亡苗胀,警方通過查閱死者的電腦和手機基协,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門应结,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泉唁,“玉大人亭畜,你說我怎么就攤上這事拴鸵【⒚辏” “怎么了聘芜?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵汰现,是天一觀的道長瞎饲。 經常有香客問我嗅战,道長驮捍,這世上最難降的妖魔是什么厌漂? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任苇倡,我火速辦了婚禮旨椒,結果婚禮上综慎,老公的妹妹穿的比我還像新娘。我一直安慰自己好港,他們只是感情好钧汹,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著录择,像睡著了一般拔莱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上隘竭,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天塘秦,我揣著相機與錄音,去河邊找鬼动看。 笑死尊剔,一個胖子當著我的面吹牛,可吹牛的內容都是我干的弧圆。 我是一名探鬼主播赋兵,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼搔预!你這毒婦竟也來了霹期?” 一聲冷哼從身側響起船庇,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎邑蒋,沒想到半個月后钱慢,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡陶珠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年暑脆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碟联。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡普监,死狀恐怖豌蟋,靈堂內的尸體忽然破棺而出允睹,到底是詐尸還是另有隱情戳吝,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響酸员,放射性物質發(fā)生泄漏。R本人自食惡果不足惜邀泉,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一因谎、第九天 我趴在偏房一處隱蔽的房頂上張望饭冬。 院中可真熱鬧患朱,春花似錦、人聲如沸拓挥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至剧辐,卻和暖如春忍啤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背戴尸。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓顽决,卻偏偏與公主長得像贡定,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子步悠,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內容

  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,093評論 4 62
  • SDWebImage托管在github上。https://github.com/rs/SDWebImage 這個類...
    XLsn0w閱讀 710評論 0 0
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,139評論 30 470
  • 癡女阿三(上) 從樓上往下看,對面的小院里有一畦菜園,剛被松了土,墻根下擠擠挨挨的...
    欣雅_47ff閱讀 713評論 1 4
  • Android中提供了View進行繪圖處理,View可以滿足大部分的繪圖需求眉尸,但是有時候,View卻顯得力不從心,...
    冰鑒IT閱讀 84,836評論 19 158