In my app, I have a List which displays a view in each row, and these views try to download an image from the Internet. I am trying to stop the List from freezing while downloading the image. The app works great on a fast network, but I am having problems getting the download to happen in the background. I have tried using the .task(priority: .background) to load the image, but it does not work. I must not be understanding something, any help is appreciated. Here is my code for the view which needs to load the images. I have my downloading code in a shared object which the view calls. Not all of the items to display have the cover property so that it is why it is optional, and I display a default image if the cover is not present.
import SwiftUI
import CoreImage
struct CoverView: View {
var cover: Int?
var size: String
var height: Double
@State private var tempImage: UIImage?
@State private var uiImage: UIImage?
@State private var modifier1 = 0.62
@State private var modifier2 = 1.0
@EnvironmentObject var downLoader: BookDownloader
var body: some View {
Group {
if cover != nil {
if let uiImage = uiImage {
Image(uiImage: uiImage)
.resizable()
.frame(width: height * modifier1, height: height * modifier2)
} else {
ProgressView()
}
}
}
.onChange(of: tempImage, perform: { newValue in
uiImage = tempImage
})
.task(priority: .background) {
if let cover = cover {
if cover > 0 {
tempImage = await downLoader.getUIImageForCover(cover: cover, size: size)
} else {
tempImage = UIImage(systemName: "x.circle")
modifier1 = 0.5
modifier2 = 0.5
}
}
}
}
}
This is the networking code in the downLoader object:
func getUIImageForCover(cover: Int, size: String) async -> UIImage? {
let urlString = getCoverImageURLString(cover: cover, size: size)
return await getUIImageForURLString(url: urlString)
}
private func getUIImageForURLString(url: String) async -> UIImage? {
do {
guard let urlToDownload = URL(string: url) else {
assert(true, "URL failed")
return nil
}
let data = try Data(contentsOf: urlToDownload)
// stores the data in the book struct so it can be saved into a BookData ultimately
book?.coverImageData = data
if let uiImage = UIImage(data: data) {
return uiImage
}
} catch {
print(error.localizedDescription)
}
return nil
}
private func getCoverImageURLString(cover: Int, size: String) -> String {
// checks to make sure the size string is of the right type
assert(size == "S" || size == "M" || size == "L", "Wrong size entered into getCoverImageURLString")
let urlString = "https://covers.openlibrary.org/b/id/\(cover)-\(size).jpg"
return urlString
}