I'm trying to display a long list of images with titles using the new AsyncImage in SwiftUI. I noticed that when I put VStack around AsyncImage and scroll through images it's reloading images every time I scroll up or down. When there's no VStack I see no reloading and images seem to stay cached.
Is there a way to make VStack not to reload images on scrolling so I can add text under each image?
Here's a working example. Try scrolling with and without VStack.
import SwiftUI
struct TestView: View {
let url = URL(string: "https://picsum.photos/200/300")
let columns: [GridItem] = [.init(.fixed(110)),.init(.fixed(110)),.init(.fixed(110))]
var body: some View {
ScrollView {
LazyVGrid(columns: columns) {
ForEach(0..<20) { _ in
// VStack here causes to images to reload on scrolling
VStack {
AsyncImage(url: url) { image in
image
.resizable()
.aspectRatio(contentMode: .fit)
} placeholder: {
Image(systemName: "photo")
.imageScale(.large)
.frame(width: 110, height: 110)
}
}
}
}
}
}
}
numpy.vstack () function is used to stack the sequence of input arrays vertically to make a single array. tup : [sequence of ndarrays] Tuple containing arrays to be stacked. The arrays must have the same shape along all but the first axis.
‘Lazy’ keyword distinguishes LazyVStack from VStack. In VStack, all views are rendered and loaded in memory as soon as view is initialized and appears on screen. In LazyVStack, only views that are visible on screen will be rendered. Views are loaded into the memory and rendered as they become visible which makes view rendering much more performant.
=VSTACK (array1, [array2],...) array The arrays to append. VSTACK returns the array formed by appending each of the array arguments in a row-wise fashion. The resulting array will be the following dimensions: Rows: the combined count of all the rows from each of the array arguments.
Because LazyVStack takes entire width provided by the parent, alignment is more apparent. Take a look at the example below: Notice that in case of VStack we have to make one capsule wide enough so rest capsule views can animate to alignment changes
I fully agree with you that this is a weird bug. I would guess that the reason it's happening has something to do with the way LazyVGrid
chooses to layout views, and that using a VStack
here gives it the impression there is more than one view to show. This is a poor job on Apple's part, but this is how I solved it: just put the VStacks
internal to the AsyncImage
. I'm not entirely sure what the original error is, but I do know that this fixes it.
struct MyTestView: View {
let url = URL(string: "https://picsum.photos/200/300")
let columns: [GridItem] = [.init(.fixed(110)),.init(.fixed(110)),.init(.fixed(110))]
var body: some View {
ScrollView {
LazyVGrid(columns: columns) {
ForEach(0..<20) { i in
AsyncImage(url: url) { image in
VStack {
image
.resizable()
.aspectRatio(contentMode: .fit)
Text("label \(i)")
}
} placeholder: {
VStack {
Image(systemName: "photo")
.imageScale(.large)
.frame(width: 110, height: 110)
Text("image broken")
}
}
}
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With