use separate caches for scaleAspectFill #13
@@ -689,8 +689,6 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
var offset = scrollingCollectionView.contentOffset
|
var offset = scrollingCollectionView.contentOffset
|
||||||
offset.y *= (screenSize.width / screenSize.height)
|
offset.y *= (screenSize.width / screenSize.height)
|
||||||
scrollingCollectionView.setContentOffset(offset, animated: false)
|
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 {
|
class ImageLoader {
|
||||||
private let cache = NSCache<NSString, UIImage>()
|
private let portraitFitCache = NSCache<NSString, UIImage>()
|
||||||
private let horCache = 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 loadingTasks: [String: (UIImage?) -> Void] = [:]
|
||||||
private var activeTokens: [String: CancellationToken] = [:]
|
private var activeTokens: [String: CancellationToken] = [:]
|
||||||
private var archives = NSCache<NSString, Archive>()
|
private let archives = NSCache<NSString, Archive>()
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
// 128 MiB
|
// 128 MiB
|
||||||
cache.totalCostLimit = 128 * 1024 * 1024
|
portraitFitCache.totalCostLimit = 128 * 1024 * 1024
|
||||||
horCache.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.
|
// 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
|
archives.countLimit = 4
|
||||||
}
|
}
|
||||||
@@ -1587,7 +1589,6 @@ class ImageLoader {
|
|||||||
loadImage(archiveURL: archiveURL, filename: filename, scaling: scaling, screenSize: screenSize, completion: nil)
|
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(
|
func loadImage(
|
||||||
archiveURL: URL, filename: String,
|
archiveURL: URL, filename: String,
|
||||||
scaling: UIView.ContentMode,
|
scaling: UIView.ContentMode,
|
||||||
@@ -1597,11 +1598,23 @@ class ImageLoader {
|
|||||||
let rotation: Rotation = screenSize.width > screenSize.height ? .horizontal : .vertical
|
let rotation: Rotation = screenSize.width > screenSize.height ? .horizontal : .vertical
|
||||||
let key = filename
|
let key = filename
|
||||||
|
|
||||||
if rotation == .vertical, let cached = cache.object(forKey: key as NSString) {
|
if scaling == .scaleAspectFit {
|
||||||
completion?(cached); return
|
if rotation == .vertical, let cached = portraitFitCache.object(forKey: key as NSString) {
|
||||||
}
|
completion?(cached); return
|
||||||
if rotation == .horizontal, let cached = horCache.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 {
|
if let existing = activeTokens[key], !existing.isCancelled {
|
||||||
@@ -1662,8 +1675,14 @@ class ImageLoader {
|
|||||||
)
|
)
|
||||||
let vScaledSize = aspectSize(for: image.size, in: vertical, scaling: scaling)
|
let vScaledSize = aspectSize(for: image.size, in: vertical, scaling: scaling)
|
||||||
let vScaleImage = resizeImage(image, to: vScaledSize)
|
let vScaleImage = resizeImage(image, to: vScaledSize)
|
||||||
if let cost = imageByteSize(vScaleImage) {
|
let cost = imageByteSize(vScaleImage)!
|
||||||
self.cache.setObject(vScaleImage, forKey: filename as NSString, cost: cost)
|
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 }
|
if rotation == .vertical { image = vScaleImage }
|
||||||
}
|
}
|
||||||
@@ -1677,8 +1696,14 @@ class ImageLoader {
|
|||||||
)
|
)
|
||||||
let hScaledSize = aspectSize(for: image.size, in: horizontal, scaling: scaling)
|
let hScaledSize = aspectSize(for: image.size, in: horizontal, scaling: scaling)
|
||||||
let hScaleImage = resizeImage(image, to: hScaledSize)
|
let hScaleImage = resizeImage(image, to: hScaledSize)
|
||||||
if let cost = imageByteSize(hScaleImage) {
|
let cost = imageByteSize(hScaleImage)!
|
||||||
self.horCache.setObject(hScaleImage, forKey: filename as NSString, cost: cost)
|
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 }
|
if rotation == .horizontal { image = hScaleImage }
|
||||||
}
|
}
|
||||||
@@ -1694,10 +1719,6 @@ class ImageLoader {
|
|||||||
loadingTasks[key] = nil
|
loadingTasks[key] = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func imageIfLoaded(at path: String) -> UIImage? {
|
|
||||||
return cache.object(forKey: path as NSString)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func imageByteSize(_ image: UIImage) -> Int? {
|
func imageByteSize(_ image: UIImage) -> Int? {
|
||||||
|
|||||||
Reference in New Issue
Block a user