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

SwiftUI中LazyVGrid内自定义Slide组件数据更新后视图不刷新问题

根本原因

你遇到的问题是SwiftUI数据流使用错误导致的:

  • Slide组件内的SlideData被声明为@State,@State是视图私有状态标识,只会在组件首次初始化时赋值一次,后续父视图传入新的slide参数时,@State修饰的SlideData不会同步更新,始终保留第一次初始化的值。
  • 同理IsSelected被声明为@State也会存在同样的问题,父视图传入的选中状态变更后子组件无法收到更新。

修复步骤

  1. 修改Slide组件的属性声明
    将不需要子组件自行修改的IsSelected改为普通常量,将需要和外部数据源同步的SlideData改为@Binding绑定类型:
struct Slide : View {
    // 仅作为私有编辑状态标识可以保留@State,建议加private限制作用域
    @State private var EnableSlideEditing : Bool? = false
    // 父视图传入的固定参数,不需要@State
    let IsSelected : Bool
    // 和外部数据源绑定,外部变更会同步到组件内
    @Binding var SlideData : SplaySlide
    @EnvironmentObject var SlideStructure : SlidesModel

    // 其余原有代码保持不变
}
  1. 修改父视图ShowSongFile中ForEach的遍历方式,传入绑定值
    遍历@Published数组时加$前缀获取每个元素的绑定,传入Slide组件:
LazyVGrid(columns: columns, alignment: .trailing, spacing: 20) {
    // 加$获取数组元素的绑定
    ForEach($SlideStructure.SongSlides, id:\.id) { $slide in
        if slide.id == selectedSlide?.id {
            Slide(IsSelected:true, SlideData: $slide)
        } else {
            Slide(IsSelected:false, SlideData: $slide)
                .onTapGesture {
                    selectSlide(Slide: slide)
                }
        }
    }
}

补充说明

你之前在LazyVGrid中直接添加Text(slide.color)能正常刷新,是因为父视图直接读取了SlidesModel中@Published修饰的最新数组值,@Published变更会触发父视图重绘,而Slide组件使用本地@State缓存了旧数据,所以不会跟随父视图重绘更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 03:15:10