I have been trying to work with the image downloader code provided in the session to see if I could download two images at once and cache them in the actor.
For some reason, when I enter the download method on the actor with two consecutive async let
calls, the app hangs at the deepest suspension point.
I am providing a very minimum code you can copy and paste into a new iOS Storyboard-based project, replacing the code in ViewController.swift
:
enum ImageDownloadError: Error {
case badImage
}
actor ImageDownloader {
private var cache: [URL: UIImage] = [:]
func image(from url: URL) async throws -> UIImage {
if let image = cache[url] {
return image
}
print("Downloading image")
let image = try await downloadImage(url: url)
print("Downloaded image")
cache[url] = image
return image
}
private func downloadImage(url: URL) async throws -> UIImage {
let imageRequest = URLRequest(url: url)
let (data, imageResponse) = try await URLSession.shared.data(for: imageRequest)
guard let image = UIImage(data: data), (imageResponse as? HTTPURLResponse)?.statusCode == 200 else {
throw ImageDownloadError.badImage
}
return image
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
async {
await downloadImages()
}
}
func downloadImages() async {
let downloader = ImageDownloader()
let imageURL = URL(string: "https://www.andyibanez.com/fairesepages.github.io/tutorials/async-await/part3/3.png")!
async let downloadedImage = downloader.image(from: imageURL)
//async let sameDownloadedImage = downloader.image(from: imageURL) // Uncomment to see the bug
var images = [UIImage?]()
images += [try? await downloadedImage]
//images += [try? await sameDownloadedImage]
print("Finished everything")
}
}
If you uncomment the code marked as Uncomment to see the bug
, you will see that the code will go through many different await calls, but it will hang on the ine in the URLSession.shared.data(for: imageRequest)
call. The app just hangs there and doesn't continue executing. Commenting the same line will let it work fine.
Are there any known workarounds for this? I would love to get this to work.
I have opened a feedback on this, linking it just in case