В этой статье мы рассмотрим, как кэшировать изображения в приложении Swift, чтобы повысить производительность вашего пользовательского интерфейса. Кэширование может быть полезно во многих сценариях, например, когда вам нужно отобразить большое количество изображений или когда вам нужно отобразить одно и то же изображение несколько раз. Кэшируя изображения, вы можете уменьшить количество загрузок вашего приложения из внешнего источника, например сервера, что может повысить скорость отклика вашего приложения и сократить использование памяти.

Мы начнем с рассмотрения того, как создать простой класс ImageCache, который можно использовать для кэширования изображений. Этот класс будет хранить изображения в объекте NSCache, который представляет собой встроенный кэш, оптимизированный для хранения изображений.

import UIKit

class ImageCache {
  // MARK: - Properties

  private let cache = NSCache<NSString, UIImage>()

  // MARK: - Caching

  func cache(image: UIImage, forKey key: String) {
    cache.setObject(image, forKey: key as NSString)
  }

  func image(forKey key: String) -> UIImage? {
    return cache.object(forKey: key as NSString)
  }
}

Чтобы использовать класс ImageCache, вы должны сначала создать его экземпляр, затем использовать метод cache(image:forKey:) для добавления изображения в кеш и метод image(forKey:) для извлечения изображения из кеша. Например:

let cache = ImageCache()

let image = UIImage(named: "myImage")
cache.cache(image: image, forKey: "myImage")

let cachedImage = cache.image(forKey: "myImage")

Класс ImageCache — это простой автономный класс, который можно использовать в любой части приложения. Однако может быть удобнее использовать кеш непосредственно из ваших экземпляров UIImageView. Для этого вы можете создать расширение для UIImageView, которое добавляет методы cache(image:forKey:) и cachedImage(forKey:).

import UIKit

extension UIImageView {
  private struct AssociatedKeys {
    static var imageCache = "imageCache"
  }

  var imageCache: ImageCache {
    get {
      if let cache = objc_getAssociatedObject(self, &AssociatedKeys.imageCache) as? ImageCache {
        return cache
      }

      let cache = ImageCache()
      objc_setAssociatedObject(self, &AssociatedKeys.imageCache, cache, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
      return cache
    }
  }

  func cache(image: UIImage, forKey key: String) {
    imageCache.cache(image: image, forKey: key)
  }

  func cachedImage(forKey key: String) -> UIImage? {
    return imageCache.image(forKey: key)
  }
}

мы можем добавить некоторые дополнительные функции в класс ImageCache, чтобы сделать его более полезным в реальном приложении. Например, мы можем добавить метод очистки кеша, когда он заполняется, а также мы можем добавить метод загрузки изображения с URL-адреса и его автоматического кэширования.

Вот обновленная версия класса ImageCache со следующими дополнительными функциями:

import UIKit

class ImageCache {
  // MARK: - Properties

  private let cache = NSCache<NSString, UIImage>()

  // MARK: - Caching

  func cache(image: UIImage, forKey key: String) {
    cache.setObject(image, forKey: key as NSString)
  }

  func image(forKey key: String) -> UIImage? {
    return cache.object(forKey: key as NSString)
  }

  func clearCache() {
    cache.removeAllObjects()
  }

  func loadImage(fromURL url: URL, forKey key: String, completion: @escaping (UIImage?) -> Void) {
    if let image = image(forKey: key) {
      completion(image)
      return
    }

    URLSession.shared.dataTask(with: url) { data, response, error in
      if let data = data, let image = UIImage(data: data) {
        self.cache(image: image, forKey: key)
        completion(image)
      } else {
        completion(nil)
      }
    }.resume()
  }
}

Благодаря этим дополнительным методам вы теперь можете использовать класс ImageCache для загрузки изображений с URL-адресов и их автоматического кэширования. Например:

let cache = ImageCache()

let imageURL = URL(string: "https://example.com/image.png")!
cache.loadImage(fromURL: imageURL, forKey: "imageKey") { image in
  // Use the image here
}

Вы также можете использовать метод clearCache() для очистки кеша, когда он заполняется, что может помочь вашему приложению не использовать слишком много памяти.

cache.clearCache()

Таким образом, кэширование изображений может повысить производительность вашего приложения за счет уменьшения количества загрузок вашего приложения из внешнего источника. Используя класс ImageCache и расширение UIImageView, показанное в этой статье, вы можете легко добавить кэширование изображений в свое приложение Swift.