parent
9b33059089
commit
d6a847bfcc
|
@ -22,6 +22,7 @@ class ImageCache {
|
|||
#endif
|
||||
|
||||
private let cache: ImageDataCache
|
||||
private let desiredPixelSize: CGSize?
|
||||
|
||||
private var groups = MultiThreadDictionary<URL, RequestGroup>(name: "ImageCache request groups")
|
||||
|
||||
|
@ -30,28 +31,47 @@ class ImageCache {
|
|||
init(name: String, memoryExpiry: CacheExpiry, diskExpiry: CacheExpiry? = nil, desiredSize: CGSize? = nil) {
|
||||
// todo: might not always want to use UIScreen.main for this, e.g. Catalyst?
|
||||
let pixelSize = desiredSize?.applying(.init(scaleX: UIScreen.main.scale, y: UIScreen.main.scale))
|
||||
self.desiredPixelSize = pixelSize
|
||||
self.cache = ImageDataCache(name: name, memoryExpiry: memoryExpiry, diskExpiry: diskExpiry, storeOriginalDataInMemory: diskExpiry == nil, desiredPixelSize: pixelSize)
|
||||
}
|
||||
|
||||
func get(_ url: URL, loadOriginal: Bool = false, completion: ((Data?, UIImage?) -> Void)?) -> Request? {
|
||||
let key = url.absoluteString
|
||||
if !ImageCache.disableCaching,
|
||||
let entry = try? cache.get(key, loadOriginal: loadOriginal) {
|
||||
if let completion = completion {
|
||||
backgroundQueue.async {
|
||||
completion(entry.data, entry.image)
|
||||
|
||||
let wrappedCompletion: ((Data?, UIImage?) -> Void)?
|
||||
if let completion = completion {
|
||||
wrappedCompletion = { (data, image) in
|
||||
if #available(iOS 15.0, *) {
|
||||
if !loadOriginal,
|
||||
let size = self.desiredPixelSize {
|
||||
image?.prepareThumbnail(of: size, completionHandler: {
|
||||
completion(data, $0)
|
||||
})
|
||||
} else {
|
||||
image?.prepareForDisplay {
|
||||
completion(data, $0)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.backgroundQueue.async {
|
||||
completion(data, image)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wrappedCompletion = nil
|
||||
}
|
||||
|
||||
if !ImageCache.disableCaching,
|
||||
let entry = try? cache.get(key, loadOriginal: loadOriginal) {
|
||||
wrappedCompletion?(entry.data, entry.image)
|
||||
return nil
|
||||
} else {
|
||||
if let group = groups[url] {
|
||||
if let completion = completion {
|
||||
return group.addCallback(completion)
|
||||
}
|
||||
return nil
|
||||
return group.addCallback(wrappedCompletion)
|
||||
} else {
|
||||
let group = createGroup(url: url)
|
||||
let request = group.addCallback(completion)
|
||||
let request = group.addCallback(wrappedCompletion)
|
||||
group.run()
|
||||
return request
|
||||
}
|
||||
|
@ -122,21 +142,15 @@ class ImageCache {
|
|||
task!.resume()
|
||||
}
|
||||
|
||||
private func updatePriority() {
|
||||
task?.priority = max(1.0, URLSessionTask.defaultPriority + 0.1 * Float(requests.filter { !$0.cancelled }.count))
|
||||
}
|
||||
|
||||
func addCallback(_ completion: ((Data?, UIImage?) -> Void)?) -> Request {
|
||||
let request = Request(callback: completion)
|
||||
requests.append(request)
|
||||
updatePriority()
|
||||
return request
|
||||
}
|
||||
|
||||
func cancelWithoutCallback() {
|
||||
if let request = requests.first(where: { $0.callback == nil && !$0.cancelled }) {
|
||||
request.cancel()
|
||||
updatePriority()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,8 +159,6 @@ class ImageCache {
|
|||
if remaining <= 0 {
|
||||
task?.cancel()
|
||||
complete(with: nil)
|
||||
} else {
|
||||
updatePriority()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue