Ответ
Эффективное кеширование изображений включает два уровня: оперативная память (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:
- Двухуровневое кеширование: Добавьте дисковое кеширование с помощью
FileManager. Сначала проверяйте RAM, затем диск, и только потом сеть. - Инвалидация кеша: Реализуйте политику очистки (например, по времени или размеру кеша).
NSCacheавтоматически очищает память при нехватке, но для диска нужна своя логика. - Очередь операций: Добавьте очередь или механизм отслеживания загрузок, чтобы избежать повторной загрузки одного изображения несколькими запросами одновременно.
- Использование готовых решений: Для большинства проектов лучше использовать оптимизированные библиотеки, такие как SDWebImage или Kingfisher, которые решают эти проблемы "из коробки".