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

SwiftUI分Section列表中跨分组Realm任务项的onDelete删除实现

分区块Realm任务列表精准删除实现方案

问题场景

基于SwiftUI构建分两类区块展示的待办清单视图:

  • 区块分为pending(待处理)、completed(已完成)两类
  • 数据层使用Realm存储,通过@ObservedResults订阅任务数据
  • 滑动删除时需要解决跨分组索引错位问题,精准定位待删除的目标任务

初始待补全逻辑的代码如下:

enum Sections: String, CaseIterable {
    case pending = "Pending"
    case completed = "Completed"
} 

struct TodoListView: View {
    
    @ObservedResults(Task.self) var tasks: Results<Task>
   
    var pendingTasks: [Task] {
        tasks.filter { $0.isCompleted == false }
    }
    
    var completedTasks: [Task] {
        tasks.filter { $0.isCompleted == true }
    }
    
    var body: some View {
        let _ = print(Self._printChanges())
        List {
            ForEach(Sections.allCases, id: \.self) { section in
                Section {
                    
                    let filteredTasks = section == .pending ? pendingTasks: completedTasks
                    
                    if filteredTasks.isEmpty {
                        Text("No tasks")
                    }
                    
                    ForEach(filteredTasks, id: \._id) { task in
                        HStack {
                            TaskCellView(task: task)
                        }
                    }.onDelete { indexSet in
                        // 待实现删除逻辑
                    }
                } header: {
                    Text(section.rawValue)
                }
            }
        }.listStyle(.plain)
    }
}

实现逻辑说明

onDelete回调返回的indexSet是当前Section内部的局部索引,不是整个List的全局索引,因此只需要获取当前分组对应的筛选后任务数组,按索引取出对应任务调用Realm删除方法即可,不会出现索引错位删错的问题。

最简实现(推荐)

直接复用当前Section作用域内已经计算完成的filteredTasks变量,无需重复做筛选计算,代码更简洁:

.onDelete { indexSet in
    indexSet.forEach { index in
        let targetTask = filteredTasks[index]
        $tasks.remove(targetTask)
    }
}

已验证可运行的冗余实现(自行编写版本)

以下代码可以正常运行,但存在重复筛选的冗余计算,不推荐:

.onDelete { indexSet in
    var filteredTasks: [Task] = []
    
    switch section {
        case .pending:
            filteredTasks = tasks.filter { $0.isCompleted == false }
        case .completed:
            filteredTasks = tasks.filter { $0.isCompleted == true }
    }
    
    indexSet.forEach { index in
        let task = filteredTasks[index]
        $tasks.remove(task)
    }
}

避坑提示:禁止直接用全局tasks数组按indexSet的索引取元素,否则会因为跨分组导致索引错位,误删其他分组的任务。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 09:57:17