SwiftUI中嵌套ForEach场景下如何自定义.onDelete(perform:)实现删除功能
解决嵌套ForEach下的.onDelete问题
我完全理解你遇到的困惑——嵌套ForEach确实会让SwiftUI原生的.onDelete(perform:)方法不好直接用,因为它默认只传递当前层级的索引集合,没法同时拿到内外层的位置信息。别担心,咱们只需要调整一下ForEach的写法,就能让删除逻辑正常工作。
核心思路
要实现内层元素的删除,咱们需要同时拿到外层Job的索引和内层Filter的索引:
- 外层
ForEach通过zip获取Job的索引和对应的元素; - 给内层
ForEach单独添加.onDelete,在闭包里结合外层的Job索引,定位到要删除的Filter。
完整代码示例
下面是调整后的代码,我还补充了基础的数据模型示例方便你参考:
struct ContentView: View { // 如果你的数据是来自ViewModel,这里可以换成@StateObject @State private var ticket = Ticket() var body: some View { List { // 外层ForEach:同时获取Job的索引和元素 ForEach(Array(zip(ticket.jobArray.indices, ticket.jobArray)), id: \.1.id) { jobIndex, job in ForEach(Array(zip(job.filters.indices, job.filters)), id: \.0) { filterIndex, filter in Text(filter) } // 给内层ForEach绑定删除逻辑 .onDelete(perform: { offsets in // 因为删除操作一次只会处理一个索引(Edit模式下),取第一个即可 guard let filterIndex = offsets.first else { return } // 修改对应Job里的filters数组 ticket.jobArray[jobIndex].filters.remove(at: filterIndex) }) } } .toolbar { EditButton() } } } // 基础数据模型示例(根据你的实际结构调整) struct Ticket { var jobArray: [Job] = [ Job(filters: ["Filter A", "Filter B"]), Job(filters: ["Filter C", "Filter D", "Filter E"]) ] } struct Job: Identifiable { let id = UUID() // 用稳定的唯一标识作为ForEach的id var filters: [String] }
关键注意事项
- 数据可变性:确保
jobArray和filters都是var类型,这样才能执行remove(at:)操作; - 视图更新触发:如果你的数据是放在
ObservableObject里的,记得把jobArray标记为@Published,这样修改数据时视图才会自动刷新:class TicketViewModel: ObservableObject { @Published var jobArray: [Job] = [/* 初始化数据 */] } - ForEach的id选择:尽量用元素的唯一标识(比如
\.1.id)而不是索引,这样数据变化时SwiftUI能更高效地更新视图。
这样调整后,你点击Edit按钮进入编辑模式,就能正常删除内层的Filter元素了~
内容的提问来源于stack exchange,提问作者Sergio Bost
相关产品推荐
相关产品推荐

