diff --git a/ImageViewer/ViewController.swift b/ImageViewer/ViewController.swift index 305b6fe..10a8c1b 100644 --- a/ImageViewer/ViewController.swift +++ b/ImageViewer/ViewController.swift @@ -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() - private let horCache = NSCache() + private let portraitFitCache = NSCache() + private let landscapeFitCache = NSCache() + private let portraitFillCache = NSCache() + private let landscapeFillCache = NSCache() private var loadingTasks: [String: (UIImage?) -> Void] = [:] private var activeTokens: [String: CancellationToken] = [:] - private var archives = NSCache() + private let archives = NSCache() 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? {