You need to enable JavaScript to run this app. SwiftUI过滤列表调用.onDelete时删除索引错误问题求解
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 03:30:02