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

优化iOS 11异步操作下leadingSwipeActions的视觉交互效果

解决UITableViewCell右滑异步操作的加载状态控制问题

咱们先明确要实现的核心效果:

  • 右滑单元格触发异步操作时,立刻显示加载指示器
  • 操作进行期间:
    • 隐藏单元格内的文本标签
    • 让单元格保持“内联”状态(不会停留在滑动展开的菜单界面)
    • 禁止用户再次滑动该单元格
    • 持续展示加载指示器直到操作完成

第一步:准备必要的状态跟踪和单元格配置

首先,我们需要一个集合来跟踪正在执行异步操作的单元格索引,避免重复触发;同时要给自定义的UITableViewCell添加加载指示器控件。

1. 自定义UITableViewCell子类

class CustomTableViewCell: UITableViewCell {
    // 你的原有内容标签
    @IBOutlet weak var contentLabel: UILabel!
    // 添加加载指示器控件
    @IBOutlet weak var activityIndicator: UIActivityIndicatorView!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // 默认隐藏加载指示器
        activityIndicator.isHidden = true
    }
    
    // 统一切换加载状态的方法
    func setLoading(_ isLoading: Bool) {
        contentLabel.isHidden = isLoading
        isLoading ? activityIndicator.startAnimating() : activityIndicator.stopAnimating()
        activityIndicator.isHidden = !isLoading
    }
}

2. 在ViewController中添加状态跟踪变量

class YourViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    // 用集合跟踪正在加载的indexPath,避免重复触发操作
    private var loadingIndexPaths = Set<IndexPath>()
    // 你的tableView实例
    @IBOutlet weak var tableView: UITableView!
    
    // ... 其他原有代码(数据源、代理方法等) ...
}

第二步:完善滑动动作配置和异步操作逻辑

接下来修改你已有的leadingSwipeActionsConfigurationForRowAt方法,加入状态判断和加载控制:

override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    // 如果当前单元格正在加载,直接返回nil,禁止用户再次滑动
    guard !loadingIndexPaths.contains(indexPath) else {
        return nil
    }
    
    let action = UIContextualAction(style: .normal, title: "执行操作") { [weak self] (action, view, completionHandler) in
        guard let self = self else {
            completionHandler(false)
            return
        }
        
        // 标记当前单元格为加载中
        self.loadingIndexPaths.insert(indexPath)
        // 立即更新单元格状态,显示加载指示器
        if let cell = tableView.cellForRow(at: indexPath) as? CustomTableViewCell {
            cell.setLoading(true)
        }
        // 调用completionHandler让单元格立刻回到内联状态
        completionHandler(true)
        
        // 替换成你的真实异步业务逻辑(这里用延迟模拟)
        DispatchQueue.global().asyncAfter(deadline: .now() + 3) {
            DispatchQueue.main.async {
                // 操作完成后移除加载标记
                self.loadingIndexPaths.remove(indexPath)
                // 恢复单元格原始状态
                if let cell = tableView.cellForRow(at: indexPath) as? CustomTableViewCell {
                    cell.setLoading(false)
                }
                // 可选:如果需要刷新数据,可调用 tableView.reloadRows(at: [indexPath], with: .automatic)
            }
        }
    }
    
    // 可以给滑动动作设置样式,比如背景色
    action.backgroundColor = .systemBlue
    return UISwipeActionsConfiguration(actions: [action])
}

关键逻辑说明

  • 状态防重复:用Set<IndexPath>记录正在加载的单元格,确保同一单元格不会被重复触发操作
  • 禁止重复滑动:创建滑动动作前先检查加载状态,存在则返回nil,用户无法再次滑动该单元格
  • 立即回到内联:触发操作后立刻调用completionHandler(true),让单元格自动收起滑动菜单,保持内联展示
  • 统一状态切换:通过自定义的setLoading(_:)方法,一键控制标签隐藏和加载指示器的显示/动画

这样就能完美实现你需要的所有效果啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:58:54