SwiftUI中移除嵌套数组元素:如何避免硬编码索引?
解决SwiftUI嵌套数组的onDelete硬编码问题
你的核心问题是onDelete的层级绑定错误:当前代码把onDelete加在了外层ForEach(items)上,导致indexSet对应的是外层items数组的索引,而非内层data数组的索引,硬编码[1]也只能固定操作第二个Item。
正确实现方式
需要把onDelete绑定到**内层遍历data的ForEach**上,同时拿到外层Item的索引,才能精准修改对应Item的data数组。具体修改如下:
- 外层
ForEach改用带索引的遍历方式,通过enumerated()获取每个Item在items数组中的位置 - 将
onDelete附加到内层ForEach上,利用外层索引定位要修改的Item
修改后的完整代码:
struct Item: Codable, Identifiable, Hashable { var id: Int var data: [Datr] } struct Datr: Codable, Identifiable, Hashable { var id: Int var number: String enum CodingKeys: String, CodingKey { case id case number = "number" } } struct ContentView: View { @State fileprivate var items = [ Item(id: 1, data: [Datr(id: 1, number: "one"), Datr(id: 2, number: "two")]), Item(id: 2, data: [Datr(id: 1, number: "three"), Datr(id: 2, number: "four")]) ] var body: some View { List { // 外层遍历同时获取索引和对应Item ForEach(Array(items.enumerated()), id: \.element.id) { itemIndex, item in // 内层遍历data数组,把onDelete绑定到这里 ForEach(item.data) { dataItem in Text(dataItem.number) } .onDelete { dataIndexSet in // 通过外层索引找到目标Item,删除其data数组中的元素 items[itemIndex].data.remove(atOffsets: dataIndexSet) } } } } }
更优架构建议
如果后续数据逻辑更复杂,建议把数据操作抽离到ObservableObject中,让视图只负责展示,符合MVVM架构:
class ItemStore: ObservableObject { @Published var items: [Item] = [ Item(id: 1, data: [Datr(id: 1, number: "one"), Datr(id: 2, number: "two")]), Item(id: 2, data: [Datr(id: 1, number: "three"), Datr(id: 2, number: "four")]) ] // 统一管理数据删除逻辑 func deleteData(fromItemAt itemIndex: Int, offsets: IndexSet) { items[itemIndex].data.remove(atOffsets: offsets) } } struct ContentView: View { @StateObject private var store = ItemStore() var body: some View { List { ForEach(Array(store.items.enumerated()), id: \.element.id) { itemIndex, item in ForEach(item.data) { dataItem in Text(dataItem.number) } .onDelete { offsets in store.deleteData(fromItemAt: itemIndex, offsets: offsets) } } } } }
这种方式把数据修改逻辑集中管理,后续扩展新增、编辑等操作会更清晰。
内容的提问来源于stack exchange,提问作者richmw
相关产品推荐
相关产品推荐

