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

