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

Swift中基于Diffable Data Source实现待办分区及任务迁移方案咨询

Swift Diffable Data Source 待办任务分区迁移解决方案

1. 重构数据源结构

把原来的二维数组拆成两个独立数组,避免索引混乱,让分区和数据的对应关系更直观:

// 定义待办任务模型,必须包含*唯一标识符*(Diffable Data Source 要求)
struct TodoItem: Hashable {
    let id: UUID // 用UUID保证每个任务唯一
    let title: String
    var isCompleted: Bool // 标记任务完成状态
}

// 替换原二维数组,拆分为两个独立数据源
var unfulfilledTodos: [TodoItem] = [] // 未完成任务集合
var completedTodos: [TodoItem] = [] // 已完成任务集合

2. 确认Section枚举定义

保持你的分区枚举,确保遵守CaseIterable和Hashable协议(Diffable 要求):

enum Section: CaseIterable, Hashable {
    case unfulfilled // 未完成分区
    case completed // 已完成分区
}

3. 重写configureSnapshot方法

用双数组直接映射对应分区,彻底解决原二维数组的匹配混乱问题:

func configureSnapshot() {
    var snapshot = NSDiffableDataSourceSnapshot<Section, TodoItem>()
    
    // 添加所有分区到快照
    snapshot.appendSections(Section.allCases)
    
    // 给对应分区绑定数据源
    snapshot.appendItems(unfulfilledTodos, toSection: .unfulfilled)
    snapshot.appendItems(completedTodos, toSection: .completed)
    
    // 应用快照更新UI
    dataSource.apply(snapshot, animatingDifferences: true)
}

4. 处理勾选框点击事件

点击勾选后,直接修改数据源数组,再重新生成快照即可完成任务迁移:

func toggleTodoCompletion(at indexPath: IndexPath) {
    guard let section = Section(rawValue: indexPath.section),
          let targetTodo = dataSource.itemIdentifier(for: indexPath) else {
        return
    }
    
    // 根据当前分区执行迁移逻辑
    switch section {
    case .unfulfilled:
        // 从未完成数组移除,更新状态后加入已完成数组
        if let index = unfulfilledTodos.firstIndex(where: { $0.id == targetTodo.id }) {
            var updatedTodo = targetTodo
            updatedTodo.isCompleted = true
            unfulfilledTodos.remove(at: index)
            completedTodos.append(updatedTodo)
        }
    case .completed:
        // 可选:支持从已完成切回未完成
        if let index = completedTodos.firstIndex(where: { $0.id == targetTodo.id }) {
            var updatedTodo = targetTodo
            updatedTodo.isCompleted = false
            completedTodos.remove(at: index)
            unfulfilledTodos.append(updatedTodo)
        }
    }
    
    // 重新生成快照更新UI
    configureSnapshot()
}

5. 数据源初始化与Cell绑定

确保Cell的勾选状态和任务数据绑定,并正确传递点击事件:

// 初始化Diffable Data Source
let dataSource = UITableViewDiffableDataSource<Section, TodoItem>(tableView: tableView) { tableView, indexPath, item in
    let cell = tableView.dequeueReusableCell(withIdentifier: "TodoCell", for: indexPath) as! TodoCell
    cell.titleLabel.text = item.title
    cell.completionCheckbox.isSelected = item.isCompleted
    // 绑定勾选框点击事件
    cell.completionCheckbox.addTarget(self, action: #selector(checkboxTapped(_:)), for: .touchUpInside)
    return cell
}

// 处理勾选框点击的响应方法
@objc func checkboxTapped(_ sender: UIButton) {
    guard let cell = sender.superview?.superview as? UITableViewCell,
          let indexPath = tableView.indexPath(for: cell) else {
        return
    }
    toggleTodoCompletion(at: indexPath)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 20:58:26