SwiftUI中如何删除ObservableObject中的嵌套数组元素
SwiftUI 滑动删除 ObservableObject 嵌套数组元素
我需要在SwiftUI中实现滑动删除操作,移除ObservableObject内嵌套数组中的元素。该ObservableObject包含外层数组resultslist,每个元素是newDataModelist对象,其内部有存储MockData实例的data数组。当用户滑动删除某个MockData元素时,要从ObservableObject中移除对应项。
目前使用onDelete修饰符只能获取到内层data数组的索引indexSet,但还需要获取外层resultslist的索引,才能对ObservableObject中的数据执行删除操作。相关代码如下:
数据模型代码
struct MockData: Codable, Identifiable, Hashable { let id: Int let name, boat, time: String let isFavourite: Bool enum CodingKeys: String, CodingKey { case id case name = "Name" case boat = "Boat" case time = "Time" } }
数据结构示例
[ newDataModelist( id: 1, date: "190623", data: [ MockData(id: 1001, name: "Rich", boat: "RS Neo", time: "10102", isFavourite: false), MockData(id: 1002, name: "Isla", boat: "RS Aero", time: "5903", isFavourite: false), MockData(id: 1003, name: "Ben", boat: "RS Aero", time: "5843", isFavourite: false), MockData(id: 1004, name: "Dar", boat: "RS Aero", time: "5783", isFavourite: false) ] ), newDataModelist( id: 2, date: "190622", data: [ MockData(id: 1005, name: "rach", boat: "RS Neo", time: "10102", isFavourite: false), MockData(id: 1006, name: "sam", boat: "RS Aero", time: "5903", isFavourite: false), MockData(id: 1007, name: "nigel", boat: "RS Aero", time: "5843", isFavourite: false), MockData(id: 1008, name: "pete", boat: "RS Aero", time: "5783", isFavourite: false) ] ) ]
当前视图代码片段
// 未完成的onDelete逻辑 .onDelete { indexSet in for n in indexSet { observeredObject.resultslist[x].data[n] } }
List { ForEach(observeredObject.resultslist) { result in ForEach(result.data) { res in HStack { Text(res.name) Spacer() Text(res.boat) Spacer() Text(res.time) } }.onDelete { indexSet in for n in indexSet { // 无法获取外层索引,无法执行删除 } } } }
解决方法
要实现需求,核心是在外层ForEach中获取对应的resultslist索引,结合内层的indexSet定位到要删除的元素,以下是两种可行方案:
方案1:直接在视图中获取外层索引
使用带索引的ForEach重载版本,同时获取外层数组的索引和对应的newDataModelist对象,然后在内层onDelete中执行删除:
List { // 外层ForEach通过enumerated()获取索引和元素 ForEach(Array(observeredObject.resultslist.enumerated()), id: \.element.id) { outerIndex, result in ForEach(result.data) { res in HStack { Text(res.name) Spacer() Text(res.boat) Spacer() Text(res.time) } }.onDelete { indexSet in // 遍历要删除的内层索引,从对应外层元素的data数组中移除 indexSet.forEach { innerIndex in // 注意:如果newDataModelist是结构体,需要先复制再修改 var updatedModel = observeredObject.resultslist[outerIndex] updatedModel.data.remove(at: innerIndex) observeredObject.resultslist[outerIndex] = updatedModel } } } }
方案2:在ObservableObject中封装删除逻辑(推荐)
遵循MVVM模式,将数据操作逻辑封装在ObservableObject内部,视图只负责触发操作:
首先确保newDataModelist的data属性是可变的(将let改为var),然后在ObservableObject类中添加删除方法:
class YourObservableObject: ObservableObject { @Published var resultslist: [newDataModelist] = [] // 封装删除逻辑:接收外层索引和内层索引集合 func deleteMockData(at outerIndex: Int, innerIndices: IndexSet) { guard outerIndex < resultslist.count else { return } var updatedModel = resultslist[outerIndex] innerIndices.forEach { innerIndex in guard innerIndex < updatedModel.data.count else { return } updatedModel.data.remove(at: innerIndex) } resultslist[outerIndex] = updatedModel } }
然后在视图中调用该方法:
List { ForEach(Array(observeredObject.resultslist.enumerated()), id: \.element.id) { outerIndex, result in ForEach(result.data) { res in HStack { Text(res.name) Spacer() Text(res.boat) Spacer() Text(res.time) } }.onDelete { indexSet in observeredObject.deleteMockData(at: outerIndex, innerIndices: indexSet) } } }
关键注意事项
- 如果
newDataModelist是结构体(值类型),修改其内部的data数组时,必须先创建副本修改,再替换回resultslist中对应的元素,否则无法触发@Published的更新。 - 如果
newDataModelist是类(引用类型),则可以直接修改data数组,无需替换整个对象。
内容的提问来源于stack exchange,提问作者richmw
相关产品推荐
相关产品推荐

