From 6dee0957ea63c0cb4b6cd21311d77ff3c6581b06 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sun, 17 Jan 2021 11:45:04 -0500 Subject: [PATCH] Remove in-memory caches of most original image data --- Tusker/Caching/ImageCache.swift | 8 +++--- Tusker/Caching/ImageDataCache.swift | 26 ++++++++++++++----- .../LoadingLargeImageViewController.swift | 6 ++--- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/Tusker/Caching/ImageCache.swift b/Tusker/Caching/ImageCache.swift index 9c09434d..b65fcea5 100644 --- a/Tusker/Caching/ImageCache.swift +++ b/Tusker/Caching/ImageCache.swift @@ -29,7 +29,7 @@ class ImageCache { private var backgroundQueue = DispatchQueue(label: "ImageCache completion queue", qos: .default) init(name: String, memoryExpiry: Expiry, diskExpiry: Expiry? = nil) { - self.cache = ImageDataCache(name: name, memoryExpiry: memoryExpiry, diskExpiry: diskExpiry) + self.cache = ImageDataCache(name: name, memoryExpiry: memoryExpiry, diskExpiry: diskExpiry, storeOriginalDataInMemory: diskExpiry == nil) } func get(_ url: URL, completion: ((Data?, UIImage?) -> Void)?) -> Request? { @@ -39,9 +39,9 @@ class ImageCache { // in performance sensitive paths. a nice optimization to DiskStorage would be adding an internal cache // of the state (unknown/exists/does not exist) of whether or not objects exist on disk so that the slow, disk I/O // path can be avoided most of the time - let (data, image) = try? cache.get(key) { + let entry = try? cache.get(key) { backgroundQueue.async { - completion?(data, image) + completion?(entry.data, entry.image) } return nil } else { @@ -67,7 +67,7 @@ class ImageCache { return try? cache.getData(url.absoluteString) } - func get(_ url: URL) -> (Data, UIImage)? { + func get(_ url: URL) -> ImageDataCache.Entry? { return try? cache.get(url.absoluteString) } diff --git a/Tusker/Caching/ImageDataCache.swift b/Tusker/Caching/ImageDataCache.swift index e548491a..ce895a00 100644 --- a/Tusker/Caching/ImageDataCache.swift +++ b/Tusker/Caching/ImageDataCache.swift @@ -11,10 +11,12 @@ import Cache class ImageDataCache { - private let memory: MemoryStorage<(Data, UIImage)> + private let memory: MemoryStorage private let disk: DiskStorage? - init(name: String, memoryExpiry: Expiry, diskExpiry: Expiry?) { + private let storeOriginalDataInMemory: Bool + + init(name: String, memoryExpiry: Expiry, diskExpiry: Expiry?, storeOriginalDataInMemory: Bool) { let memoryConfig = MemoryConfig(expiry: memoryExpiry) self.memory = MemoryStorage(config: memoryConfig) @@ -24,6 +26,8 @@ class ImageDataCache { } else { self.disk = nil } + + self.storeOriginalDataInMemory = storeOriginalDataInMemory } func has(_ key: String) throws -> Bool { @@ -37,29 +41,30 @@ class ImageDataCache { } } - func get(_ key: String) throws -> (Data, UIImage)? { + func get(_ key: String) throws -> Entry? { if try memory.existsObject(forKey: key) { return try! memory.object(forKey: key) } else if let disk = self.disk, try disk.existsObject(forKey: key), let data = try? disk.object(forKey: key), let image = UIImage(data: data) { - return (data, image) + return Entry(data: data, image: image) } else { return nil } } func getImage(_ key: String) throws -> UIImage? { - return try get(key)?.1 + return try get(key)?.image } func getData(_ key: String) throws -> Data? { - return try get(key)?.0 + return try get(key)?.data } func set(_ key: String, data: Data, image: UIImage) throws { - memory.setObject((data, image), forKey: key) + let entry = Entry(data: storeOriginalDataInMemory ? data : nil, image: image) + memory.setObject(entry, forKey: key) if let disk = self.disk { try disk.setObject(data, forKey: key) @@ -72,3 +77,10 @@ class ImageDataCache { } } + +extension ImageDataCache { + struct Entry { + let data: Data? + let image: UIImage + } +} diff --git a/Tusker/Screens/Large Image/LoadingLargeImageViewController.swift b/Tusker/Screens/Large Image/LoadingLargeImageViewController.swift index 24b33afe..997ca4cd 100644 --- a/Tusker/Screens/Large Image/LoadingLargeImageViewController.swift +++ b/Tusker/Screens/Large Image/LoadingLargeImageViewController.swift @@ -85,8 +85,8 @@ class LoadingLargeImageViewController: UIViewController, LargeImageAnimatableVie overrideUserInterfaceStyle = .dark view.backgroundColor = .black - if let (data, image) = cache.get(url) { - createLargeImage(data: data, image: image, url: url) + if let entry = cache.get(url) { + createLargeImage(data: entry.data, image: entry.image, url: url) } else { createPreview() @@ -115,7 +115,7 @@ class LoadingLargeImageViewController: UIViewController, LargeImageAnimatableVie } } - private func createLargeImage(data: Data, image: UIImage, url: URL) { + private func createLargeImage(data: Data?, image: UIImage, url: URL) { guard !loaded else { return } loaded = true