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

SwiftUI onDelete()获取删除行ID重复异常求助

问题分析

你遇到的核心问题是:未将已标记删除的ID从列表数据源中排除,导致滑动删除后界面行重新显示,后续删除操作的索引指向了错误的元素;同时你的删除逻辑仅处理单个索引,且存在冗余代码。

解决方案
  1. 调整filteredTodos的过滤规则,把已标记为待删除的ID排除在外,确保界面上删除的行真正消失;
  2. 遍历indexSet中的所有索引,批量收集待删除ID,支持多选删除;
  3. 移除无意义的冗余判断代码。
修改后的代码
import SwiftUI

struct TodoItem: Identifiable {
    var id: String
    var todoID: String
    var todoName: String
    var isCompleted: Bool = false
}

final class TodoList: ObservableObject {
    
    @Published var items: [TodoItem] = [TodoItem]()
    @Published var appIsLoading: Bool = false
    
    var sortedTodos: [TodoItem] {
        return self.items.sorted { $0.todoName < $1.todoName }
    }
    
    func fetchTodos() {
        self.appIsLoading = true
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            self.items = [
                TodoItem(id: "aaa", todoID: "aaa", todoName: "Take Out Trash", isCompleted: false),
                TodoItem(id: "bbb", todoID: "bbb", todoName: "Clean Room", isCompleted: true),
                TodoItem(id: "ccc", todoID: "ccc", todoName: "Check Mail", isCompleted: false),
                TodoItem(id: "ddd", todoID: "ddd", todoName: "Walk The Dog", isCompleted: true)
            ]
            
            self.appIsLoading = false
        }
        
    }
}

struct TodoListView: View {
    
    var todosArray: [TodoItem]
    var appIsLoading: Bool
    
    @State private var hideCompleted: Bool = false
    @State private var arrayOfTodosToDelete: [String] = [String]()
    
    private var filteredTodos: [TodoItem] {
        return self.todosArray.filter { todo in
            // 新增:排除已标记待删除的ID
            !arrayOfTodosToDelete.contains(todo.todoID) && 
            !(self.hideCompleted && todo.isCompleted)
        }
    }
    
    func deleteTodo(atOffsets indexSet: IndexSet) {
        // 遍历所有待删除的索引,收集ID
        indexSet.forEach { index in
            let todo = filteredTodos[index]
            arrayOfTodosToDelete.append(todo.todoID)
        }
    }
    
    func onSubmit() {
        print("Current Array is \(self.arrayOfTodosToDelete)")
        // 这里处理网络同步逻辑
        // 同步完成后可以清空待删除数组,或者更新原数据源
        // arrayOfTodosToDelete.removeAll()
    }
    
    var body: some View {
        ZStack {
            
            List {
                ForEach(filteredTodos) { todo in
                    Text(todo.todoName)
                }.onDelete(perform: deleteTodo)
            }
            
            if appIsLoading { Text("Loading") }
            
        }.navigationTitle("Todos")
            .toolbar(content: {
                
                ToolbarItem(placement: .topBarLeading) {
                    Button(action: {
                        withAnimation {
                            self.hideCompleted.toggle()
                        }
                    }, label: {
                        Text("Hide")
                    })
                }
                
                ToolbarItem(placement: .topBarTrailing) {
                    Button(action: {
                        self.onSubmit()
                    }, label: {
                        Text("Save")
                    })
                }
                
            })
    }
}

struct ContentView: View {
    
    @StateObject var todosList = TodoList()

    private func getData() {
        self.todosList.fetchTodos()
    }
    
    var body: some View {
        ZStack {
            NavigationView {
                TodoListView(todosArray: todosList.sortedTodos, appIsLoading: todosList.appIsLoading)
            }
        }.onAppear {
            self.getData()
        }
    }
}

#Preview {
    ContentView()
}
关键修改点
  • 过滤逻辑:在filteredTodos中新增!arrayOfTodosToDelete.contains(todo.todoID),确保已标记删除的元素不再显示在界面上;
  • 删除逻辑:用indexSet.forEach遍历所有待删除索引,批量收集ID,同时移除了冗余的todoToDelete变量和无用判断;
  • 界面更新:现在滑动删除后,行会真正从界面消失,后续删除操作的索引会正确对应剩余元素。

内容的提问来源于stack exchange,提问作者Clay_F

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 17:40:52