SwiftUI问题:使用NavigationLink切换视图后复选标记消失
问题:子视图返回后复选框状态丢失
开发带复选标记列表的App时,从子视图返回主视图后再次进入,之前的选择会消失。尝试用UserDefaults保存Toggle状态,但未达到预期效果。
核心问题
所有CheckView实例共用同一个UserDefaults键"locationToggle",导致所有复选框状态互相覆盖;同时@State是视图级状态,子视图销毁后状态会丢失,重新进入时会重置初始值。
解决方案
- 为每个复选框生成唯一的UserDefaults键,用
CountriesItem的id作为键的一部分,保证每个项目状态独立存储。 - 在
CheckView初始化时直接从UserDefaults读取初始状态,替代onAppear触发读取,避免视图重建时的状态重置。 - 优化计数逻辑,确保仅在状态真正变化时调整计数,避免重复加减。
修改后的代码
CheckView
struct CheckView: View { @State private var isChecked: Bool @EnvironmentObject var numofitems: NumOfItems let itemId: UUID var title: String var count: Int = 0 init(title: String, itemId: UUID) { self.title = title self.itemId = itemId // 初始化时从UserDefaults读取对应项目的状态 self._isChecked = State(initialValue: UserDefaults.standard.bool(forKey: "toggle_\(itemId.uuidString)")) } var body: some View { HStack { Toggle(title, isOn: $isChecked) .toggleStyle(CheckToggleStyle()) .tint(.mint) .onChange(of: isChecked) { newValue in // 更新对应项目的UserDefaults状态 UserDefaults.standard.set(newValue, forKey: "toggle_\(itemId.uuidString)") // 根据状态变化调整计数 numofitems.num += newValue ? 1 : -1 } Spacer() } } }
主视图 CheckListView
struct CheckListView: View { @State private var menu = Bundle.main.decode([ItemsSection].self, from: "items.json") var body: some View { NavigationView { List { ForEach(menu) { section in NavigationLink(section.name) { ScrollView { ForEach(section.items) { item in // 传入item的id,用于生成唯一存储键 CheckView(title: item.name, itemId: item.id) } } } } } } .navigationBarHidden(true) .navigationViewStyle(StackNavigationViewStyle()) .listStyle(GroupedListStyle()) } }
补充说明
- 每个复选框的状态通过
toggle_\(itemId.uuidString)键单独存储,不会互相干扰。 - 初始化时直接读取UserDefaults,确保进入子视图时能立即恢复之前的选择状态。
- 计数逻辑仅在状态切换时触发,避免视图重建导致的重复计数问题。
内容的提问来源于stack exchange,提问作者paulatraveler
相关产品推荐
相关产品推荐

