如何在TableViewCell中实现撤销功能?撤销按钮失效问题求助
嘿,我看了你这段实现TableViewCell撤销功能的代码,发现几个关键问题导致撤销没正常工作,咱们一步步来修正:
核心问题分析
- 撤销注册时机完全搞反了:你现在是点击撤销按钮时才注册撤销操作,这根本没法记录之前的删除行为——撤销操作必须在执行删除动作的同时注册,这样
undoManager才知道要恢复什么。 - Target对象错误:你把
GoalCell.self作为撤销的target,但Cell本身不负责数据源的维护,撤销/恢复操作应该针对管理数据源的对象(比如你的ViewController)。 - Undo逻辑顺序错误:先注册再调用
undo(),相当于刚记录就撤销,完全没起到保存删除状态的作用。
修正后的代码示例
1. 重写删除方法(关键:删除前注册撤销)
// 假设你有一个存储数据的数组,比如goalsArray var goalsArray: [Goal] = [] @objc func removeGoal(atIndexPath indexPath: IndexPath) { // 第一步:先保存要删除的数据和位置,用于后续恢复 let deletedGoal = goalsArray[indexPath.row] let deleteInfo = (goal: deletedGoal, indexPath: indexPath) // 第二步:注册撤销操作——当用户点击撤销时,会调用restoreGoal方法 undoManager?.registerUndo(withTarget: self, selector: #selector(restoreGoal(_:)), object: deleteInfo) // 第三步:执行实际的删除操作 goalsArray.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .automatic) }
2. 添加恢复数据的方法
@objc func restoreGoal(_ info: (goal: Goal, indexPath: IndexPath)) { // 恢复数据到数据源 goalsArray.insert(info.goal, at: info.indexPath.row) tableView.insertRows(at: [info.indexPath], with: .automatic) // 额外注册"重做"操作——让用户撤销后还能再次删除 undoManager?.registerUndo(withTarget: self, selector: #selector(removeGoal(atIndexPath:)), object: info.indexPath) }
3. 修正撤销按钮的点击方法
@IBAction func undoBtnWasPressed(_ sender: Any) { // 先检查是否有可撤销的操作,避免崩溃 guard let undoManager = undoManager, undoManager.canUndo else { undoView.isHidden = true return } undoManager.undo() // 根据是否还有可撤销操作,决定是否隐藏撤销视图 undoView.isHidden = !undoManager.canUndo }
关键逻辑说明
- 撤销的核心是记录操作的逆过程:删除时保存被删数据和位置,注册恢复动作;恢复时再注册删除动作,实现"撤销-重做"的循环。
undoManager的target必须是能执行对应selector的对象,这里用self(ViewController),因为它掌控着数据源和TableView的更新。- 每次操作后记得检查
canUndo,避免无意义的空操作。
内容的提问来源于stack exchange,提问作者user6421566
相关产品推荐
相关产品推荐

