SwiftUI中LazyVGrid内自定义Slide组件数据更新后视图不刷新问题
根本原因
你遇到的问题是SwiftUI数据流使用错误导致的:
- Slide组件内的
SlideData被声明为@State,@State是视图私有状态标识,只会在组件首次初始化时赋值一次,后续父视图传入新的slide参数时,@State修饰的SlideData不会同步更新,始终保留第一次初始化的值。 - 同理
IsSelected被声明为@State也会存在同样的问题,父视图传入的选中状态变更后子组件无法收到更新。
修复步骤
- 修改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 // 其余原有代码保持不变 }
- 修改父视图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
相关产品推荐
相关产品推荐

