Что происходит с SDWebImage Cached Images в моем приложении при изменении файла изображения на сервере?

Я использую SDWebImage библиотека для кэширования веб-изображений в моем приложении:

https://github.com/rs/SDWebImage/blob/master/README.md

Текущее использование:

[imageView setImageWithURL:[NSURL URLWithString:profilePictureUrl] placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

У меня вопрос: что произойдет, когда изображение будет кэшировано, а затем через пару дней этот файл изображения на сервере будет обновлен новым образом?

На данный момент мое приложение все еще отображает кэшированное изображение.

Я не вижу ни в одной документации по настройке тайм-аута кэша или чего-то, что распознает, что размер файла изменился.

Если у кого-то есть опыт использования этой конкретной библиотеки, то любая помощь будет принята с благодарностью.

Заранее спасибо.

10 ответов

Решение

Я посмотрел на исходный код. Обрабатывает setImageWithURL метод как это:

  1. Спросите кеш памяти, если изображение есть, если да, верните изображение и не идите дальше
  2. Спросите кеш диска, есть ли изображение, если да, верните изображение и не идите дальше
  3. Попробуйте загрузить изображение, вернуть изображение в случае успеха, иначе сохранить изображение заполнителя

Не отправляется запрос, чтобы спросить удаленный сервер, есть ли новая версия, когда на диске есть что-то старое, например, использование ETag протокола HTTP.

Если копнуть немного глубже, то время кеша устанавливается в статическое значение в SDImageCache.m

static NSInteger cacheMaxCacheAge = 60*60*24*7; // 1 week

это не может быть изменено с помощью сеттера.

Так что пока изображение в кеше действительно SDWebImage lib не будет загружать ничего нового Через неделю он загрузит ваше измененное изображение.

Ты можешь использовать options параметр.

Swift версия:

imageView.sd_setImage(with: URL(string: URLWithString:profilePictureUrl),
                      placeholderImage: UIImage(named: "placeholder"),
                      options: .refreshCached,
                      completed: nil)

Версия Objective-C:

[imageView sd_setImageWithURL:[NSURL URLWithString:profilePictureUrl]
             placeholderImage:[UIImage imageNamed:@"placeholder.png"]
             options:SDWebImageRefreshCached
             completed: nil];

Ура!

Проблема со старением SDImageCache (который теперь имеет сеттер: maxCacheAge) заключается в том, что SDWebImage никогда не делает с ним ничего проактивного. Вам нужно вызвать cleanDisk самостоятельно в какой-то момент, чтобы удалить старые данные из кэша. Примечание: SDWebImage вызывает cleanDisk, когда приложение завершает свою работу, но приложениям не гарантируется получение уведомления о завершении из ОС.

    NSURL *imageUrl = nil;
    NSDate *lastUpdate = [[NSUserDefaults standardUserDefaults] objectForKey:@"lastUpdate"];
    NSDate *currentDate = [NSDate date];

    if (lastUpdate == nil 
        || ![lastUpdate isKindOfClass:[NSDate class]] 
        || [currentDate timeIntervalSinceDate:lastUpdate] > 60 * 60 *24) {
            [[NSUserDefaults standardUserDefaults] setObject:currentDate forKey:@"lastUpdate"];
            NSString *urlString = [NSString stringWithFormat:@"http://yourdomain.com/image/image.png?%f", [currentDate timeIntervalSince1970]];
            imageUrl = [NSURL URLWithString:urlString];
    }

Если вы хотите изменить длительность кэша по умолчанию в Swift. Установите это в вашем AppDelegate.

Версия 3:

SDWebImageManager.sharedManager().imageCache.maxCacheAge = CACHE_TIME_IN_SECONDS

Версия 4:

SDWebImageManager.shared().imageCache?.config.maxCacheAge = CACHE_TIME_IN_SECONDS

-

Я считаю, что это влияет только на изображения, которые являются кэшами после установки этого значения. То есть, если ваше приложение кэширует изображение с истечением срока действия кэша по умолчанию, а затем изменяет его на что-то другое, ваши изображения все еще будут иметь срок действия только через неделю. Простое решение этой проблемы - просто очистить кеш.

Ниже то, что я заметил.

  1. Если имя / путь к изображению совпадают, SDWebImage не будет загружать его снова в течение 1 недели.

  2. Независимо от имени изображения, SDWebImage повторно загрузит изображение через 1 неделю (с момента его загрузки).

    static NSInteger cacheMaxCacheAge = 60*60*24*7; // 1 week

  3. У них есть одна база данных, где хранятся все изображения URL. Для них URL-адрес изображения похож на первичный ключ (уникальный ключ).

Таким образом, в основном, что они делают, если URL-адрес изменен и отсутствует в БД, загрузите его.

С моей точки зрения, то, что они делают, ПРАВИЛЬНО. Ex. Если вы загружаете изображение, скажем, для пользователя А, имя изображения должно быть изменено, и это является основным. Я знаю, что некоторые разработчики предпочитают, чтобы имя изображения было одинаковым (как и у userA.png всегда).

SDWebImage выполняет агрессивное кэширование по умолчанию. Но теперь они дают возможность уважать ваши заголовки управления кэшированием HTTP и получать последние изображения.

Для этого у них есть новый метод, где в настройках вы можете передать SDWebImageRefreshCached

[imageView sd_setImageWithURL:[NSURL URLWithString:@"https://graph.facebook.com/xyz/picture"]
             placeholderImage:[UIImage imageNamed:@"avatar-placeholder.png"]
                      options:SDWebImageRefreshCached];

Вы можете найти полную информацию о методе и объяснение здесь.

Поток SDWebImage:

1) SDWebImage кэширует изображение, полученное с сервера

2) SDWebImage использует url-ключ для получения изображения из кеша

3) SDWebImage проверки:

если он может получить изображение из кеша - ОК

если нет (например, URL был изменен) - не удалось получить изображение из кэша

так что на самом деле, вы получите пустой ImageView (ы) и SDWebImage необходимо снова получить изображения с сервера

Последний Swift 3.0* и SDWebImage

SDWebImageManager.shared().imageCache?.deleteOldFiles(completionBlock: nil)

Как я прочитал в readme SDWeb в git, это может помочь:

В вашем случае вы можете использовать SDWebImageRefreshCached флаг. Это немного ухудшит производительность, но будет учитывать заголовки элемента управления HTTP-кэшированием:

[imageView sd_setImageWithURL:[NSURL URLWithString:@"https://graph.facebook.com/olivier.poitrey/picture"]
                 placeholderImage:[UIImage imageNamed:@"avatar-placeholder.png"]
                          options:SDWebImageRefreshCached];
Другие вопросы по тегам