在 LazyVStack 中使用 VStack 和 AsyncImage 会导致图像在滚动时重新加载

Mak*_*aus 16 swift swiftui swiftui-list lazyvgrid

我正在尝试使用 SwiftUI 中的新 AsyncImage 显示一长串带有标题的图像。我注意到,当我将 VStack 放在 AsyncImage 周围并滚动图像时,每次向上或向下滚动时它都会重新加载图像。当没有 VStack 时,我看不到重新加载,并且图像似乎保留在缓存中。

有没有办法让 VStack 在滚动时不重新加载图像,以便我可以在每个图像下添加文本?

这是一个工作示例。尝试使用和不使用 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)
                        }
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 12

我完全同意你的观点,这是一个奇怪的错误。我猜想,发生这种情况的原因与选择布局视图的方式有关LazyVGrid,并且使用此处VStack给人的印象是有多个视图要显示。对于苹果来说,这是一个糟糕的工作,但这就是我解决它的方法:只需将内部VStacks放入AsyncImage. 我不完全确定最初的错误是什么,但我确实知道这可以解决它。

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")
                        }
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)