You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LazyVGrid中VStack包裹AsyncImage滚动时图片重加载如何解决?

问题根因

这个现象的本质是LazyVGrid的懒加载复用机制要求子视图拥有可预判的尺寸,你当前没有给VStack添加明确的尺寸约束,滚动时视图被回收后重新进入可视区,SwiftUI会重新计算VStack的布局并重建内部所有子视图,导致AsyncImage被重新初始化,触发重复加载。

解决方法

方法1:给VStack添加明确的固定尺寸

直接指定VStack的宽高,让LazyVGrid可以直接复用回收的视图,无需重新构造内部的AsyncImage,即可解决重复加载问题,同时你也可以在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, id: \.self) { index in
                    VStack(spacing: 6) {
                        AsyncImage(url: url) { image in
                            image
                                .resizable()
                                .aspectRatio(contentMode: .fit)
                                .frame(width: 110, height: 110)
                        } placeholder: {
                            Image(systemName: "photo")
                                .imageScale(.large)
                                .frame(width: 110, height: 110)
                        }
                        // 可自由添加图片标题
                        Text("图片\(index + 1)")
                            .font(.caption)
                            .lineLimit(1)
                    }
                    // 明确指定VStack的总尺寸,适配图片+文本的高度
                    .frame(width: 110, height: 136)
                }
            }
        }
    }
}

方法2:固定AsyncImage的尺寸

如果不想给VStack写死高度,也可以保证AsyncImage的加载状态、占位状态的尺寸完全一致,这样VStack的尺寸可以被SwiftUI提前计算出来,也不会触发视图重建。
使用这种方法时,只需要给AsyncImage外层加固定宽高的frame即可,不需要给VStack指定高度。

方法3:使用稳定的视图ID

给ForEach添加稳定的唯一ID,避免滚动时视图ID变化导致的视图重建,业务场景中推荐使用图片的唯一标识或者URL作为ID。

内容的提问来源于stack exchange,提问作者Maklaus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 10:57:03