Как реализовать кеширование изображений в iOS?

«Как реализовать кеширование изображений в iOS?» — вопрос из категории Алгоритмы и структуры данных, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Эффективное кеширование изображений включает два уровня: оперативная память (RAM) и дисковое хранилище. Это ускоряет повторное отображение и снижает нагрузку на сеть.

Базовая реализация с NSCache (кеш в памяти):

class ImageCache {
    static let shared = ImageCache()
    private let memoryCache = NSCache<NSString, UIImage>()

    func loadImage(from url: URL, completion: @escaping (UIImage?) -> Void) {
        let cacheKey = url.absoluteString as NSString

        // 1. Проверка кеша в памяти
        if let cachedImage = memoryCache.object(forKey: cacheKey) {
            completion(cachedImage)
            return
        }

        // 2. Загрузка из сети, если нет в кеше
        URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
            guard let self = self,
                  let data = data,
                  let image = UIImage(data: data), 
                  error == nil else {
                completion(nil)
                return
            }

            // 3. Сохранение в кеш памяти
            self.memoryCache.setObject(image, forKey: cacheKey)

            DispatchQueue.main.async {
                completion(image)
            }
        }.resume()
    }
}

Улучшения для production:

  1. Двухуровневое кеширование: Добавьте дисковое кеширование с помощью FileManager. Сначала проверяйте RAM, затем диск, и только потом сеть.
  2. Инвалидация кеша: Реализуйте политику очистки (например, по времени или размеру кеша). NSCache автоматически очищает память при нехватке, но для диска нужна своя логика.
  3. Очередь операций: Добавьте очередь или механизм отслеживания загрузок, чтобы избежать повторной загрузки одного изображения несколькими запросами одновременно.
  4. Использование готовых решений: Для большинства проектов лучше использовать оптимизированные библиотеки, такие как SDWebImage или Kingfisher, которые решают эти проблемы "из коробки".