SwiftUI中如何修改@EnvironmentObject列表中的数据?
问题分析与解决方案
你的核心问题是编辑数据后MainView未同步更新,主要由两个原因导致:编辑状态未正确初始化、值类型数组的更新未触发@Published通知,以下是具体解决步骤:
1. 初始化编辑页面的状态变量
当前EditFishingView中的fishingName和fishingType初始值为空,打开编辑页面时不会显示原有数据,导致保存时可能未真正修改内容。需要在页面出现时将状态变量初始化为当前fishing的属性值:
struct EditFishingView: View { @EnvironmentObject var fishingData: FishingData @Binding var fishing: Fishing @Binding var showEditView: Bool @State private var fishingName: String = "" @State private var fishingType: FishingType = .fishingLog var body: some View { ScrollView(.vertical, showsIndicators: false) { VStack(alignment: .leading, spacing: 10) { EF_HeaderView(fishing: $fishing, fishingName: $fishingName, fishingType: $fishingType) } .shadow(color: .gray, radius: 4, x: 0, y: 2) .padding(10) } .background(Color(red: 242/255, green: 242/255, blue: 247/255)) .navigationBarTitleDisplayMode(.inline) .navigationTitle(fishing.name) // 添加onAppear初始化状态 .onAppear { fishingName = fishing.name fishingType = fishing.type } .toolbar { // 原有toolbar代码不变 } } }
2. 确保数组更新触发视图刷新
由于Fishing是值类型,仅修改Binding对象的属性不会触发@Published var mockFishings的更新通知(数组整体值未改变)。需要直接修改并替换数组中的元素,强制触发@Published的更新:
// 修改EditFishingView中"Готово"按钮的逻辑 Button("Готово") { guard let index = fishingData.mockFishings.firstIndex(where: { $0.id == fishing.id }) else { showEditView = false return } // 创建修改后的副本 var updatedFishing = fishingData.mockFishings[index] updatedFishing.name = fishingName updatedFishing.type = fishingType // 替换数组元素,触发@Published更新 fishingData.mockFishings[index] = updatedFishing print("fishingData ID\(index)") print(updatedFishing.name) print(fishingData.mockFishings[index].name) print("Fishing ID\(updatedFishing.id)") showEditView = false }
3. 简化导航链接的写法(可选优化)
当前MainView中用透明NavigationLink的写法容易引发状态异常,建议改为常规写法:
// MainView中的List部分修改为: List { ForEach($fishingData.mockFishings) { $fishing in NavigationLink(destination: DetailFishingView(fishing: $fishing)) { FishingItem(fishingData: fishing) } .listRowBackground(RoundedRectangle(cornerRadius: 10) .fill(Color.white) .padding(2)) } .onDelete(perform: { indexSet in fishingData.delete(indexSet) }) }
内容的提问来源于stack exchange,提问作者Vital
相关产品推荐
相关产品推荐

