You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中移除嵌套数组元素:如何避免硬编码索引?

解决SwiftUI嵌套数组的onDelete硬编码问题

你的核心问题是onDelete的层级绑定错误:当前代码把onDelete加在了外层ForEach(items)上,导致indexSet对应的是外层items数组的索引,而非内层data数组的索引,硬编码[1]也只能固定操作第二个Item。

正确实现方式

需要把onDelete绑定到**内层遍历data的ForEach**上,同时拿到外层Item的索引,才能精准修改对应Item的data数组。具体修改如下:

  1. 外层ForEach改用带索引的遍历方式,通过enumerated()获取每个Item在items数组中的位置
  2. 将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 20:04:59