Add another layer of caching in PHAssetImage
- ID
1b0855e- date
2023-06-09 16:24:20+00:00- author
Alex Chan <alex@alexwlchan.net>- parent
fa2167f- message
Add another layer of caching in PHAssetImage- changed files
1 file, 22 additions
Changed files
BlinkReviewer/BlinkReviewer/Views/PHAssetImage.swift (3463) → BlinkReviewer/BlinkReviewer/Views/PHAssetImage.swift (4458)
diff --git a/BlinkReviewer/BlinkReviewer/Views/PHAssetImage.swift b/BlinkReviewer/BlinkReviewer/Views/PHAssetImage.swift
index ddf6e54..a938b88 100644
--- a/BlinkReviewer/BlinkReviewer/Views/PHAssetImage.swift
+++ b/BlinkReviewer/BlinkReviewer/Views/PHAssetImage.swift
@@ -27,6 +27,7 @@ class PHAssetImage: NSObject, ObservableObject {
init(_ asset: PHAsset?, size: CGSize, deliveryMode: PHImageRequestOptionsDeliveryMode) {
self.size = size
self.deliveryMode = deliveryMode
+ self.imageCache = Dictionary()
super.init()
@@ -37,6 +38,18 @@ class PHAssetImage: NSObject, ObservableObject {
private var size: CGSize
private var deliveryMode: PHImageRequestOptionsDeliveryMode
+ // Often we'll be retrieving the same image repeatedly, as the user shuttles
+ // back and forth between a few images they're comparing. In this case, we
+ // don't want to go back to Photos every time -- so we keep a cache of images
+ // we've retrieved previously.
+ //
+ // In theory the `PHCachingImageManager` does this for us; in practice the app
+ // feels snappier to me with this additional cache.
+ //
+ // TODO: Replace this Dictionary with an LRU cache of some sort; this could
+ // allow the app's memory usage to balloon indefinitely.
+ private var imageCache: Dictionary<PHAsset, NSImage>
+
var asset: PHAsset? {
get {
self._asset
@@ -50,6 +63,11 @@ class PHAssetImage: NSObject, ObservableObject {
private func regenerateImage() {
if let thisAsset = asset {
+ if let nsImage = imageCache[thisAsset] {
+ self.image = nsImage
+ return
+ }
+
// This implementation is based on code in a Stack Overflow answer
// by Francois Nadeau: https://stackoverflow.com/a/48755517/1558022
@@ -83,6 +101,10 @@ class PHAssetImage: NSObject, ObservableObject {
if let imageResult = result {
self.image = imageResult
+
+ if !self.isDegraded {
+ self.imageCache[thisAsset] = imageResult
+ }
} else {
print("Error getting image: \(info)")
}