use separate caches for scaleAspectFill

This commit was merged in pull request #13.
This commit is contained in:
2026-07-13 00:55:06 +02:00
parent 2f0e7f1821
commit 00b3a28a62
+42 -21
View File
@@ -689,8 +689,6 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
var offset = scrollingCollectionView.contentOffset
offset.y *= (screenSize.width / screenSize.height)
scrollingCollectionView.setContentOffset(offset, animated: false)
// FIXME: This is a caching issue, needs a different cache for scrolling since it Fill instead of Fit.
scrollingCollectionView.reloadData()
}
}
@@ -1569,16 +1567,20 @@ enum Rotation {
}
class ImageLoader {
private let cache = NSCache<NSString, UIImage>()
private let horCache = NSCache<NSString, UIImage>()
private let portraitFitCache = NSCache<NSString, UIImage>()
private let landscapeFitCache = NSCache<NSString, UIImage>()
private let portraitFillCache = NSCache<NSString, UIImage>()
private let landscapeFillCache = NSCache<NSString, UIImage>()
private var loadingTasks: [String: (UIImage?) -> Void] = [:]
private var activeTokens: [String: CancellationToken] = [:]
private var archives = NSCache<NSString, Archive>()
private let archives = NSCache<NSString, Archive>()
init() {
// 128 MiB
cache.totalCostLimit = 128 * 1024 * 1024
horCache.totalCostLimit = 128 * 1024 * 1024
portraitFitCache.totalCostLimit = 128 * 1024 * 1024
landscapeFitCache.totalCostLimit = 128 * 1024 * 1024
portraitFillCache.totalCostLimit = 128 * 1024 * 1024
landscapeFillCache.totalCostLimit = 128 * 1024 * 1024
// The reason archives are cached and have a strict limit of four, is because Archive supposedly opens a posix file pointer and keeps it until the object is destroyed.
archives.countLimit = 4
}
@@ -1587,7 +1589,6 @@ class ImageLoader {
loadImage(archiveURL: archiveURL, filename: filename, scaling: scaling, screenSize: screenSize, completion: nil)
}
// FIXME: So scrolling is not really handled well in terms of caching. This is because it should have a separate cache since it uses a different scaling (Fill instead of Fit).
func loadImage(
archiveURL: URL, filename: String,
scaling: UIView.ContentMode,
@@ -1597,11 +1598,23 @@ class ImageLoader {
let rotation: Rotation = screenSize.width > screenSize.height ? .horizontal : .vertical
let key = filename
if rotation == .vertical, let cached = cache.object(forKey: key as NSString) {
completion?(cached); return
}
if rotation == .horizontal, let cached = horCache.object(forKey: key as NSString) {
completion?(cached); return
if scaling == .scaleAspectFit {
if rotation == .vertical, let cached = portraitFitCache.object(forKey: key as NSString) {
completion?(cached); return
}
if rotation == .horizontal, let cached = landscapeFitCache.object(forKey: key as NSString) {
completion?(cached); return
}
} else if scaling == .scaleAspectFill {
if rotation == .vertical, let cached = portraitFillCache.object(forKey: key as NSString) {
completion?(cached); return
}
if rotation == .horizontal, let cached = landscapeFillCache.object(forKey: key as NSString) {
completion?(cached); return
}
} else {
print("this should not be reachable")
return
}
if let existing = activeTokens[key], !existing.isCancelled {
@@ -1662,8 +1675,14 @@ class ImageLoader {
)
let vScaledSize = aspectSize(for: image.size, in: vertical, scaling: scaling)
let vScaleImage = resizeImage(image, to: vScaledSize)
if let cost = imageByteSize(vScaleImage) {
self.cache.setObject(vScaleImage, forKey: filename as NSString, cost: cost)
let cost = imageByteSize(vScaleImage)!
if scaling == .scaleAspectFit {
self.portraitFitCache.setObject(vScaleImage, forKey: filename as NSString, cost: cost)
} else if scaling == .scaleAspectFill {
self.portraitFillCache.setObject(vScaleImage, forKey: filename as NSString, cost: cost)
} else {
print("this should be unreachable")
return
}
if rotation == .vertical { image = vScaleImage }
}
@@ -1677,8 +1696,14 @@ class ImageLoader {
)
let hScaledSize = aspectSize(for: image.size, in: horizontal, scaling: scaling)
let hScaleImage = resizeImage(image, to: hScaledSize)
if let cost = imageByteSize(hScaleImage) {
self.horCache.setObject(hScaleImage, forKey: filename as NSString, cost: cost)
let cost = imageByteSize(hScaleImage)!
if scaling == .scaleAspectFit {
self.landscapeFitCache.setObject(hScaleImage, forKey: filename as NSString, cost: cost)
} else if scaling == .scaleAspectFill {
self.landscapeFillCache.setObject(hScaleImage, forKey: filename as NSString, cost: cost)
} else {
print("this should be unreachable")
return
}
if rotation == .horizontal { image = hScaleImage }
}
@@ -1694,10 +1719,6 @@ class ImageLoader {
loadingTasks[key] = nil
}
}
func imageIfLoaded(at path: String) -> UIImage? {
return cache.object(forKey: path as NSString)
}
}
func imageByteSize(_ image: UIImage) -> Int? {