SDWebImage支持URL不变时更新图片内容

关于SDWebImage支持URL不变时更新图片内容的问题,博客这里有了很好的解释,可供参考。

结论就是当图片url不变,内容更新了后,想要客户端更新图片缓存需要做两步:

  1. 加载图片的地方设置OptionSDWebImageRefreshCached
  2. 在诸如AppDelegate didFinishLaunching的地方追加如下代码
SDWebImageDownloader *imgDownloader = SDWebImageManager.sharedManager.imageDownloader;
imgDownloader.headersFilter  = ^NSDictionary *(NSURL *url, NSDictionary *headers) {
NSFileManager *fm = [[NSFileManager alloc] init];
        NSString *imgKey = [SDWebImageManager.sharedManager cacheKeyForURL:url];
        NSString *imgPath = [SDWebImageManager.sharedManager.imageCache defaultCachePathForKey:imgKey];
        NSDictionary *fileAttr = [fm attributesOfItemAtPath:imgPath error:nil];
        
        NSMutableDictionary *mutableHeaders = [headers mutableCopy];
        
        NSDate *lastModifiedDate = nil;
        
        if (fileAttr.count > 0) {
            if (fileAttr.count > 0) {
                lastModifiedDate = (NSDate *)fileAttr[NSFileModificationDate];
            }
            
        }
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
        formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
        formatter.dateFormat = @"EEE, dd MMM yyyy HH:mm:ss z";
        
        NSString *lastModifiedStr = [formatter stringFromDate:lastModifiedDate];
        lastModifiedStr = lastModifiedStr.length > 0 ? lastModifiedStr : @"";
        [mutableHeaders setValue:lastModifiedStr forKey:@"If-Modified-Since"];
        
        return mutableHeaders;
}

这段代码是以本地url对应的缓存图片更新时间转换成If-Modified-Since的value值传给服务器,服务器拿到该值后与服务端的Last-Modified值做对比,而本地转换的总是和服务端不相等,导致同一张图片实际上是不断从服务器下载更新了,验证方法:
(1)在沙盒中查看同一张图片的更新时间,是一直变化的
(2)在block中打断点,查看SDImageCacheType

[self.imageView sd_setImageWithURL:url placeholderImage:defaultImage options:SDWebImageRefreshCached completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {} 

下载图片时查看SDImageCacheType 值,会发现一张图片会断两次,第一从缓存读取,第二次为cacheType 值为 SDImageCacheTypeNone,重新下载了一次更新本地图片,也就是会一直从服务器下载图片更新本地,显然不合逻辑。
更好的做法还是严格的将Last-ModifiedETag值缓存起来,url为key,下载图片时将Last-ModifiedETag回传给服务器,两个一起传更好。通过查看SDWebImage源码发现,每次下载图片收到服务器响应时,会发送SDWebImageDownloadReceiveResponseNotification通知,将SDWebImageDownloaderOperation 作为参数传出,而SDWebImageDownloaderOperation有response和request,那么就好办了,我们取出response中的Last-ModifiedEtag作为value值,同时取出request的RUR.absoluteString作为key,缓存起来,请求图片时将url对应的Last-ModifiedETag取出在SDWebImageDownloaderheadersFilter设置一下传给服务器,有服务器来进行对比。有关服务器的对比逻辑请查看以上参考链接。具体代码如下:

#pragma mark -  配置sdwebImage headersFilter
-(void)sdWebImageConfig{
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdWebImageDownloadReceiveResponseNotification:) name:SDWebImageDownloadReceiveResponseNotification object:nil];
    
    SDWebImageDownloader *imgDownloader = SDWebImageManager.sharedManager.imageDownloader;
    imgDownloader.headersFilter  = ^NSDictionary *(NSURL *url, NSDictionary *headers) {
       
        NSMutableDictionary *mutableHeaders = [headers mutableCopy];
        
        NSString * lastModifiedStr = [[SBAppCoreInfo getCacheDB] getStrValue:EMGlobal_LastModified_Cache  dataKey:url.absoluteString];
        NSString * etagStr = [[SBAppCoreInfo getCacheDB] getStrValue:EMGlobal_ETag_Cache   dataKey:url.absoluteString];
        
        [mutableHeaders setValue:lastModifiedStr forKey:@"If-Modified-Since"];
        [mutableHeaders setValue:etagStr forKey:@"If-None-Match"];

        return mutableHeaders;
    };
}

-(void)sdWebImageDownloadReceiveResponseNotification:(NSNotification *)note{
    SDWebImageDownloaderOperation *  downloaderOperation = (SDWebImageDownloaderOperation *)note.object;
    NSString * urlKey = downloaderOperation.request.URL.absoluteString;
     NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)downloaderOperation.response;
    //缓存Last-Modified、ETag值
    [[SBAppCoreInfo getCacheDB] setStrValue:EMGlobal_LastModified_Cache dataKey:urlKey dataValue:httpResponse.allHeaderFields[@"Last-Modified"]];
    [[SBAppCoreInfo getCacheDB] setStrValue:EMGlobal_ETag_Cache dataKey:urlKey dataValue:httpResponse.allHeaderFields[@"ETag"]];
}

其中 EMGlobal_LastModified_CacheEMGlobal_ETag_Cache是定义的宏

[[SBAppCoreInfo getCacheDB] setStrValue:EMGlobal_LastModified_Cache dataKey:urlKey dataValue:httpResponse.allHeaderFields[@"Last-Modified"]];
[[SBAppCoreInfo getCacheDB] getStrValue:EMGlobal_LastModified_Cache  dataKey:url.absoluteString];

这两个方法为自己封装的缓存类,我们也可以用plist缓存这两个值。这样沙盒中的图片不会一直更新,只有同一个url图片发生改变,即服务端图片的Last-ModifiedETag发生改变,才会更新客户端该图片的缓存
如何查看图片url的Last-ModifiedETag值?在终端 输入

curl 图片url --head

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容