SwiftUI中孙视图更新后如何实时刷新主视图图片?
SwiftUI三层视图状态同步问题解决
三层SwiftUI视图结构中,点击第三层ExLibrisCategoryItem的图片后,顶层ExLibrisStyleView的选中图标无法实时更新,只有关闭重开页面才会生效。核心问题是iconValue的@State和@Binding使用错误,导致状态无法在视图间同步。
错误原因
- 顶层
ExLibrisStyleView中,iconValue用@State初始化时仅从UserDefaults读取一次,后续UserDefaults变化不会触发视图刷新;且传递给子视图时是传值而非绑定,子视图修改的是独立副本,无法同步回顶层。 - 中间层
ExLibrisCategoryRow错误地用@State声明iconValue,应该用@Binding接收顶层的状态绑定,才能将子视图的修改同步回去。
修正方案
- 顶层改用
@AppStorage替代@State,它会自动同步UserDefaults的变化,同时具备@State的视图刷新能力。 - 传递
iconValue时使用绑定语法$iconValue,确保子视图能修改顶层的状态。 - 中间层
ExLibrisCategoryRow将@State var iconValue改为@Binding var iconValue,接收顶层的绑定并传递给第三层。 - 第三层
ExLibrisCategoryItem的点击事件直接修改绑定的iconValue,@AppStorage会自动将值保存到UserDefaults,无需手动调用UserDefaults.set。
修正后的ExLibrisStyleView视图
import SwiftUI struct ExLibrisStyleView: View { @EnvironmentObject var exlibrisData: ExLibrisModelData // 用@AppStorage替代@State,自动同步UserDefaults并触发视图刷新 @AppStorage("iconValue") var iconValue: String = "exlibris-0" var body: some View { NavigationView{ List { VStack(alignment: .leading) { Text("Selected Bookmark") .font(.headline) .padding(.bottom,15) Image(iconValue) .renderingMode(.original) .resizable() .frame(width: 130, height: 130) .cornerRadius(5) .shadow(color: Color(red:0, green:0, blue:0, opacity:0.25), radius: 8, x: 0, y: 0) } .padding(.leading, 15) .padding(.bottom,30) .listStyle(.inset) .listRowInsets(EdgeInsets()) ForEach(exlibrisData.categories.keys.sorted(), id: \.self) { key in // 传递绑定给子视图 ExLibrisCategoryRow(categoryName: key, items: exlibrisData.categories[key]!, iconValue: $iconValue) } .listRowInsets(EdgeInsets()) } .listStyle(.inset) .navigationTitle("Bookmark Collection") } } }
修正后的ExLibrisCategoryRow视图
import SwiftUI struct ExLibrisCategoryRow: View { var categoryName: String var items: [ExLibris] // 用@Binding接收顶层的状态绑定 @Binding var iconValue: String var body: some View { VStack(alignment: .leading) { Text(categoryName) .font(.headline) .padding(.leading, 15) ScrollView(.horizontal, showsIndicators: false) { HStack(alignment: .top, spacing: 0) { ForEach(items) { exlibris in label: do { // 传递绑定给第三层视图 ExLibrisCategoryItem(exlibris: exlibris, iconValue: $iconValue) } } } } .frame(height: 200) } } }
修正后的ExLibrisCategoryItem视图
import SwiftUI struct ExLibrisCategoryItem: View { var exlibris: ExLibris @Binding var iconValue: String var body: some View { VStack(alignment: .leading) { Image(exlibris.imageName) .renderingMode(.original) .resizable() .frame(width: 130, height: 130) .cornerRadius(5) .onTapGesture { // 直接修改绑定的iconValue,@AppStorage会自动保存到UserDefaults iconValue = exlibris.imageName } } .padding(.leading, 15) } }
内容的提问来源于stack exchange,提问作者baymak
相关产品推荐
相关产品推荐

