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

Swift中如何通过长按UICollectionViewCell实现删除并刷新数据?

解决UICollectionView长按删除Cell的问题

你当前的代码有两个核心问题导致功能失效:

  • 长按手势被错误地添加到了控制器的view上,而且还是在didSelectItemAt方法内添加——这意味着只有点击过cell之后,整个页面才会响应长按,完全没关联到具体的cell;
  • 删除逻辑没有绑定选中cell的索引,没法精准删除对应的数据和cell。

下面是分步的修复方案:

1. 给每个CollectionCell添加长按手势

我们需要在创建cell的时候,直接给每个cell绑定长按手势,而不是给整个view加。修改你的cellForItemAt方法:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionCell
    let note = Model.dataList[indexPath.item]
    cell.imageView.image = note.image
    cell.titleLbl.text = note.title
    
    // 先移除cell上已有的手势,避免复用cell时重复添加
    cell.gestureRecognizers?.forEach { cell.removeGestureRecognizer($0) }
    // 创建长按手势,绑定回调方法
    let longPressGes = UILongPressGestureRecognizer(target: self, action: #selector(didLongPressCell(_:)))
    cell.addGestureRecognizer(longPressGes)
    
    return cell
}

2. 实现长按回调与删除逻辑

接下来编写长按手势的回调方法,这里我们通过手势的view(也就是当前cell)来获取对应的indexPath,确保能精准定位要删除的项:

@objc func didLongPressCell(_ gesture: UILongPressGestureRecognizer) {
    // 只在手势开始时触发,避免重复弹出弹窗
    guard gesture.state == .began, 
          let cell = gesture.view as? CollectionCell, 
          let indexPath = collectionView.indexPath(for: cell) else {
        return
    }
    
    // 弹出确认删除的弹窗
    let actionController = UIAlertController(title: "Delete", message: "Are You Sure...?", preferredStyle: .actionSheet)
    
    // 删除动作
    let deleteAction = UIAlertAction(title: "Delete Current Record", style: .destructive) { [weak self] _ in
        guard let self = self else { return }
        // 1. 先删除数据源中的数据
        Model.dataList.remove(at: indexPath.item)
        // 2. 动画删除对应的cell,performBatchUpdates会自动处理界面刷新
        self.collectionView.performBatchUpdates({
            self.collectionView.deleteItems(at: [indexPath])
        }, completion: nil)
    }
    
    // 取消动作
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
    
    actionController.addAction(deleteAction)
    actionController.addAction(cancelAction)
    self.present(actionController, animated: true)
}

3. 清理错误代码

最后,一定要删除你之前在didSelectItemAt方法里添加的手势代码,也就是这段:

let tapGes = UILongPressGestureRecognizer(target: self, action: #selector(self.didlongPress(tapGes:))) 
self.view.addGestureRecognizer(tapGes)

这段代码会让整个控制器view响应长按,干扰cell的手势逻辑。

关键说明

  • 直接给cell绑定手势,才能让每个cell独立响应长按事件;
  • 使用collectionView.indexPath(for: cell)获取索引比用tag更可靠,避免数据源变动后索引不匹配的问题;
  • 用weak self避免循环引用,这是Swift开发的最佳实践;
  • performBatchUpdates配合deleteItems能实现平滑的删除动画,不需要额外调用reloadData或reloadItems。

内容的提问来源于stack exchange,提问作者Daniyal Ali Kausar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:35:31