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
相关产品推荐
相关产品推荐

