Use background image preparation apis on iOS 15

Closes #128
This commit is contained in:
Shadowfacts 2022-02-06 10:24:07 -05:00
parent 9b33059089
commit d6a847bfcc
1 changed files with 30 additions and 18 deletions

View File

@ -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()
}
}