SwiftUI过滤列表调用.onDelete时删除索引错误问题求解
解决方案
核心逻辑是:先通过searchResults拿到要删除的元素实例,再去原数组ingredientsStore.items里匹配对应索引执行删除,避免直接用过滤后的索引操作原数组。
方法1:通过元素ID匹配删除(最稳妥,推荐)
从你代码里的ForEach直接传入数组可判断,你的Ingredient模型已经实现了Identifiable协议,直接修改deleteItems方法即可:
func deleteItems(at offsets: IndexSet) { withAnimation { // 1. 先从过滤后的结果里拿到要删除的元素 offsets.forEach { index in let targetIngredient = searchResults[index] // 2. 再去原数组里匹配对应元素的真实索引 if let originalIndex = ingredientsStore.items.firstIndex(where: { $0.id == targetIngredient.id }) { ingredientsStore.items.remove(at: originalIndex) } } } }
优势:不管搜索过滤逻辑怎么调整,都不会出现删除错位问题,容错率最高
方法2:无Identifiable的兼容方案
如果你的模型暂时没有实现Identifiable,也可以通过配料的唯一属性(如名称name,需保证属性值唯一)匹配:
func deleteItems(at offsets: IndexSet) { withAnimation { offsets.forEach { index in let targetName = searchResults[index].name if let originalIndex = ingredientsStore.items.firstIndex(where: { $0.name == targetName }) { ingredientsStore.items.remove(at: originalIndex) } } } }
大数据量优化方案
如果你的配料列表数据量超过千条,可以给Ingredient模型加Hashable协议,直接用firstIndex(of:)查找,性能更高:
// 模型修改示例 struct Ingredient: Identifiable, Hashable { let id = UUID() var name: String // 其他业务属性... } // 删除方法简化 func deleteItems(at offsets: IndexSet) { withAnimation { offsets.map { searchResults[$0] } .compactMap { ingredientsStore.items.firstIndex(of: $0) } .forEach { ingredientsStore.items.remove(at: $0) } } }
内容的提问来源于stack exchange,提问作者DenJS
相关产品推荐
相关产品推荐

