I'm trying to use an AsyncImage
to show a ProgressView
while it gets an image from a URL, but if it fails to get the image then a different image should be displayed. My code is working in the sense that it will show the different image if the AsyncImage
fails to get an image, but I can't get a placeholder ProgressView
to show while the async operation is running. The code below does not contain the placeholder modifier and works OK (EDIT: Actually unconfirmed if it's working...):
var body: some View {
AsyncImage(url: url, scale: scale ?? 1) { phase in
if let image = phase.image {
image
.resizable()
.aspectRatio(contentMode: contentMode ?? .fit)
.frame(width: width, height: height)
} else {
Image("placeholder_img")
.resizable()
.frame(width: 50, height: 50)
.border(Color(.NeutralPalette5))
.padding()
.aspectRatio(contentMode: .fill)
}
}
.frame(width: width, height: height)
}
But adding a placeholder modifier to this code does not work:
var body: some View {
AsyncImage(url: url, scale: scale ?? 1) { phase in
if let image = phase.image {
image
.resizable()
.aspectRatio(contentMode: contentMode ?? .fit)
.frame(width: width, height: height)
} else {
Image("placeholder_img")
.resizable()
.frame(width: 50, height: 50)
.border(Color(.NeutralPalette5))
.padding()
.aspectRatio(contentMode: .fill)
}
} placeholder: {
ProgressView()
.progressViewStyle(.circular)
}
.frame(width: width, height: height)
}
The above results in the following error:
Failed to produce diagnostic for expression; please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the project
Can anyone tell me how I can use a placeholder with my code? I'm basically trying to show a ProgressView
while the AsyncImage
gets the image, but if it fails to get the image then a different image should be displayed, so if there's a better way to do that please let me know.
When you use AsyncImage(url: ...)
with a placeholder: {..}
you have the image
, not the phase
.
var body: some View {
AsyncImage(url: url) { image in // <-- here
image.resizable()
} placeholder: {
ProgressView().progressViewStyle(.circular)
}
}
To present a different image, presumably after a certain time has passed, you will have to create the code yourself. Or use the following approach with the phase
:
AsyncImage(url: url) { phase in
if let image = phase.image {
image.resizable() // Displays the loaded image.
} else if phase.error != nil {
Image("Goofy") // Indicates an error, show default image
} else {
// Acts as a placeholder.
ProgressView().progressViewStyle(.circular)
// Image("Mickey Mouse")
}
}