Just slightly tweaking @mayoff's answer which seems sensible to me (accounting for the deprecations):
struct Image {
let url: URL
}
actor ImageDownloader {
private var cache = [URL: Task<Image, Error>]()
func image(for url: URL) async throws -> Image {
if let imageTask = cache[url] {
switch await imageTask.result {
case .success(let image):
return image
case .failure:
cache[url] = nil
}
}
let imageTask = Task {
try await downloadImage(url: url)
}
cache[url] = imageTask
switch await imageTask.result {
case .success(let image):
return image
case .failure(let error):
cache[url] = nil
throw error
}
}
private func downloadImage(url: URL) async throws -> Image {
print("Downloading image - \(url.absoluteString)")
try await Task.sleep(nanoseconds: 2 * 1_000_000_000)
return Image(url: url)
}
}
And you can test this using:
let imageDownloader = ImageDownloader()
async let image1 = try imageDownloader.image(for: URL(string: "https://test.com")!)
async let image2 = try imageDownloader.image(for: URL(string: "https://test.com")!)
async let image3 = try imageDownloader.image(for: URL(string: "https://test.com")!)
async let anotherImage = try imageDownloader.image(for: URL(string: "https://another.test.com")!)
print(try await image1.url.absoluteString)
print(try await image2.url.absoluteString)
print(try await image3.url.absoluteString)
print(try await anotherImage.url.absoluteString)
Which should give:
Downloading image - https://test.com
Downloading image - https://another.test.com
https://test.com
https://test.com
https://test.com
https://another.test.com
Which shows only two calls to downloadImage(url:) were actually made.
Post
Replies
Boosts
Views
Activity
A couple of answers on what the improvement could look like have been posted here: https://developer.apple.com/forums/thread/682032
Is HLS Content Steering available on Safari as well?