iOS:如何单独禁用UITableViewCell的单侧滑动操作而非整体编辑?
解决方案:单独禁用UITableView某一侧的滑行动作
当然可以实现你要的效果!canEditRowAt确实是控制整行是否允许编辑(包括所有方向的滑行动作),没法单独针对某一侧做限制。不过我们可以通过动态生成滑动操作配置的方式,根据每行的当前状态来决定是否返回对应侧的滑行动作,从而实现单侧禁用的需求。
核心思路
- 给你的数据模型添加一个状态标记(比如
isDisabled),用来记录该行当前是“已禁用”还是“正常启用”状态; - 在
leadingSwipeActionsConfigurationForRowAt和trailingSwipeActionsConfigurationForRowAt方法中,根据当前行的状态动态返回对应的滑动配置:- 当行处于已禁用状态时:只允许
leading侧的“取消禁用”动作,trailing侧返回空配置(禁用该侧滑动); - 当行处于正常启用状态时:只允许
trailing侧的“禁用”动作,leading侧返回空配置(禁用该侧滑动);
- 当行处于已禁用状态时:只允许
- 点击滑动动作后,更新对应行的状态标记,刷新该行以触发配置重新生成。
代码示例
假设你的数据模型是这样的:
struct YourModel { var content: String var isDisabled: Bool // 标记该行是否被禁用 }
然后在你的UITableViewDelegate实现中:
// 处理leading侧滑动(取消禁用) override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let model = yourDataSource[indexPath.row] // 如果当前行未被禁用,直接返回空配置(禁用leading侧滑动) guard model.isDisabled else { return UISwipeActionsConfiguration(actions: []) } // 创建“取消禁用”动作 let enableAction = UIContextualAction(style: .normal, title: "取消禁用") { [weak self] (action, view, completionHandler) in // 更新模型状态 self?.yourDataSource[indexPath.row].isDisabled = false // 刷新该行 tableView.reloadRows(at: [indexPath], with: .automatic) completionHandler(true) } enableAction.backgroundColor = .systemGreen return UISwipeActionsConfiguration(actions: [enableAction]) } // 处理trailing侧滑动(禁用行) override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let model = yourDataSource[indexPath.row] // 如果当前行已被禁用,直接返回空配置(禁用trailing侧滑动) guard !model.isDisabled else { return UISwipeActionsConfiguration(actions: []) } // 创建“禁用”动作 let disableAction = UIContextualAction(style: .destructive, title: "禁用") { [weak self] (action, view, completionHandler) in // 更新模型状态 self?.yourDataSource[indexPath.row].isDisabled = true // 刷新该行 tableView.reloadRows(at: [indexPath], with: .automatic) completionHandler(true) } disableAction.backgroundColor = .systemRed return UISwipeActionsConfiguration(actions: [disableAction]) } // 注意:canEditRowAt要保持返回true,因为我们需要允许整行的编辑权限,只是动态控制某一侧的动作 override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { return true }
原理说明
- 当我们在某一侧的配置方法中返回
UISwipeActionsConfiguration(actions: [])时,系统会认为该侧没有可执行的滑行动作,从而禁用该侧的滑动交互; - 通过
reloadRows刷新该行后,下次滑动时系统会重新调用对应的配置方法,根据更新后的状态生成正确的滑动操作; canEditRowAt返回true保证了整行处于可编辑状态,这样我们才有机会动态控制两侧的滑动动作。
这样就能完美实现你要的状态切换:点击“禁用”后,trailing侧滑动消失,leading侧出现“取消禁用”;点击“取消禁用”后则反过来。
内容的提问来源于stack exchange,提问作者Andrew P.
相关产品推荐
相关产品推荐

