iOS评论区点击添加按钮出现两个单元格的原因及修复
问题分析与修复方案
我来帮你拆解这个重复添加单元格的问题,结合你给出的三次更新信息,核心原因和解决办法如下:
核心原因
1. CommentsTapped方法被意外重复触发
从你的更新3可以确定:每次点击添加评论按钮时,CommentsTapped都会执行一遍。而这个方法里包含了清空评论数组→重新加载所有评论→刷新表格的全量更新逻辑。这就导致:
- 你手动调用
insertRows插入了临时评论行 - 同时
CommentsTapped触发的全量刷新又把后端刚保存的新评论加载了一遍 - 两者叠加就出现了重复的单元格
至于为什么用单次updateChildValues会触发这个问题,大概率是:
- 单次更新触发了Firebase的数据监听回调(比如
observe(.value)),而这个回调间接调用了CommentsTapped或者触发了评论面板的刷新 - 或者添加评论的按钮位于
CommentsTapped对应的手势识别View范围内,点击按钮时同时触发了按钮的IBAction和手势的CommentsTapped方法
2. 手动插入行与全量刷新的冲突
你在AddCommentButton里手动插入临时评论行,而CommentsTapped里又执行了arrayOfComments.removeAll()+reloadData,这两个操作的叠加会让表格同时渲染手动插入的临时行和重新加载的正式行,直接造成重复。
修复步骤
1. 阻止CommentsTapped在添加评论时被误触发
方案A:给手势识别加触发判断
修改CommentsTapped,让它只在评论面板从隐藏变显示时执行加载逻辑,避免重复触发:
@objc func CommentsTapped(_ tap: UITapGestureRecognizer) { // 只有当评论面板处于隐藏状态时,才执行打开和加载逻辑 guard p3CommentContainer.isHidden else { return } // 原来的打开面板代码 p3CommentContainer.isHidden = false self.commentsVC1.commentCellDelegate!.updateP3CommentSheet(frame: self.initalFrame.offsetBy(dx: 0, dy: 900)) self.arrayOfComments.removeAll() self.commentsVC1.tableView.reloadData() UIView.animate(withDuration: 0.2, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.9, options: .curveEaseOut, animations: { self.loadComments({ print("completed?") self.commentsVC1.tableView.reloadData() }) }) self.commentsVC1.commentCellDelegate!.updateP3CommentSheet(frame: self.initalFrame.offsetBy(dx: 0, dy: 180)) self.commentsVC1.selectedMedia = self.selectedPost?.interimMedia[self.numberMedia] self.commentsVC1.numberMedia = self.numberMedia }
方案B:临时禁用手势(如果按钮和手势范围重叠)
如果是按钮点击同时触发了手势,就在添加评论的过程中临时禁用手势:
@IBAction func AddCommentButton(_ sender: Any) { // 找到对应的点击手势并禁用 if let tapGesture = self.p3CommentContainer.gestureRecognizers?.first(where: { $0 is UITapGestureRecognizer }) { tapGesture.isEnabled = false } fetchCurrentUsersInfo() { self.addComment() { // 你的现有插入临时评论、刷新表格代码 self.tableView.beginUpdates() let cell = self.tableView.dequeueReusableCell(withIdentifier: "commentCell", for: [self.arrayOfComments.count]) as! commentTableViewCell self.tableView.insertRows(at: [NSIndexPath(row: self.arrayOfComments.count-1, section: 0) as IndexPath], with: .automatic) self.addTemporaryComment(cell: cell) self.tableView.endUpdates() self.addCommentTextField.text = "" // 操作完成后重新启用手势 DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { if let tapGesture = self.p3CommentContainer.gestureRecognizers?.first(where: { $0 is UITapGestureRecognizer }) { tapGesture.isEnabled = true } } } } }
2. 优化评论更新逻辑,避免重复刷新
把临时评论和正式评论的更新逻辑分离,避免手动插入和全量刷新冲突:
- 给你的评论模型加一个
isTemporary布尔属性,标记临时评论 - 在
addComment回调里,先把临时评论加入arrayOfComments,调用insertRows展示 - 当Firebase数据监听回调触发时(收到正式评论数据),遍历
arrayOfComments,找到isTemporary为true的项替换成正式评论,或者直接移除临时项并插入正式项,而不是清空整个数组再重新加载
3. 检查数据监听回调
如果是updateChildValues触发了数据监听回调,进而导致CommentsTapped执行,那你需要修改监听逻辑:
- 把全量的
observe(.value)改成增量的observe(.childAdded),只处理新增的评论,避免全量刷新 - 确保监听回调里不会调用
CommentsTapped或者触发不必要的面板刷新
内容的提问来源于stack exchange,提问作者user11182249




