Swift中Firebase文档无法删除,疑似时序问题求助
Firebase文档删除无反应问题排查与修复
将数据加载到TableView后,用户点击单元格本应删除对应的Firebase文档,但操作无任何反应。已确认代码正常执行、error为nil且文档ID存在,却无法完成删除。
原数据加载代码
self.comments = [] for index in 0...1 { var postCategory = "" if index == 0 { postCategory = "cPosts" } else { postCategory = "rPosts"} db.collection(postCategory).order(by: "rankValue", descending: true).getDocuments { snapshot, error in guard error == nil else { print(error!); return } for postDoc in snapshot!.documents { self.getUsername(uid: self.uid!) { username in self.secondGroup.enter() self.ref = self.db.collection(postCategory).document(postDoc.documentID).collection("comments") self.ref?.whereField("username", isEqualTo: username).getDocuments { snapshot, error in guard error == nil else { print(error!); return } for doc in snapshot!.documents { let comment = Comment(data: doc.data()) comment.docID = doc.documentID self.comments.append(comment) self.firstGroup.enter() self.repRef = self.db.collection(postCategory).document(postDoc.documentID).collection("comments").document(comment.docID).collection("replies") self.repRef?.whereField("username", isEqualTo: username).getDocuments { snapshot, error in guard error == nil else { print(error!); return } for doc in snapshot!.documents { let reply = Reply(data: doc.data()) reply.docID = doc.documentID self.comments.append(reply) } self.firstGroup.leave() } } self.firstGroup.notify(queue: .main) { self.secondGroup.leave() } self.secondGroup.notify(queue: .main) { completion(self.ref!, self.repRef!) } } } } } }
原删除代码
self.ref?.document(self.comments[indexPath.row].docID).collection("replies").getDocuments { snapshot, error in guard error == nil else { print(error!); return } for doc in snapshot!.documents { doc.reference.delete { error in guard error == nil else { print(error!); return } } } } self.ref?.document(self.comments[indexPath.row].docID!).delete { error in guard error == nil else { print(error!); return } print() } self.repRef?.document(self.comments[indexPath.row].docID).delete { error in print("ranhere also") guard error == nil else { print(error!); return } }
问题根源
- 全局引用被覆盖:循环遍历
cPosts和rPosts时,全局变量ref和repRef会被最后一次循环的集合引用覆盖,导致删除时使用错误的Firebase集合路径。 - 缺少关键路径信息:
Comment和Reply模型仅保存自身的docID,未记录所属的帖子分类、帖子文档ID,删除时无法定位到正确的文档位置。 - 类型区分缺失:
comments数组混合了Comment和Reply类型,删除代码未做区分,导致回复的删除路径完全错误。
修复方案
1. 扩展模型类
给Comment和Reply添加必要的路径字段,用于定位文档:
class Comment { var docID: String? var postCategory: String? // 记录所属分类:cPosts/rPosts var postDocID: String? // 记录所属帖子的文档ID // 原有字段... init(data: [String: Any]) { // 原有初始化逻辑... } } class Reply { var docID: String? var postCategory: String? var postDocID: String? var parentCommentDocID: String? // 记录所属评论的文档ID // 原有字段... init(data: [String: Any]) { // 原有初始化逻辑... } }
2. 修正数据加载逻辑
移除全局ref/repRef,给每个Comment和Reply设置完整的路径信息,同时优化DispatchGroup的使用:
self.comments = [] let mainGroup = DispatchGroup() for index in 0...1 { let postCategory = index == 0 ? "cPosts" : "rPosts" mainGroup.enter() db.collection(postCategory).order(by: "rankValue", descending: true).getDocuments { snapshot, error in guard let snapshot = snapshot, error == nil else { print(error!) mainGroup.leave() return } let postGroup = DispatchGroup() for postDoc in snapshot.documents { postGroup.enter() self.getUsername(uid: self.uid!) { username in let commentsRef = self.db.collection(postCategory).document(postDoc.documentID).collection("comments") commentsRef.whereField("username", isEqualTo: username).getDocuments { commentSnapshot, error in guard let commentSnapshot = commentSnapshot, error == nil else { print(error!) postGroup.leave() return } let replyGroup = DispatchGroup() for commentDoc in commentSnapshot.documents { replyGroup.enter() // 初始化并设置Comment的路径信息 var comment = Comment(data: commentDoc.data()) comment.docID = commentDoc.documentID comment.postCategory = postCategory comment.postDocID = postDoc.documentID self.comments.append(comment) // 加载该评论下的回复 let repliesRef = commentsRef.document(comment.docID!).collection("replies") repliesRef.whereField("username", isEqualTo: username).getDocuments { replySnapshot, error in guard let replySnapshot = replySnapshot, error == nil else { print(error!) replyGroup.leave() return } for replyDoc in replySnapshot.documents { // 初始化并设置Reply的路径信息 var reply = Reply(data: replyDoc.data()) reply.docID = replyDoc.documentID reply.postCategory = postCategory reply.postDocID = postDoc.documentID reply.parentCommentDocID = comment.docID self.comments.append(reply) } replyGroup.leave() } } replyGroup.notify(queue: .main) { postGroup.leave() } } } } postGroup.notify(queue: .main) { mainGroup.leave() } } } mainGroup.notify(queue: .main) { // 数据加载完成后刷新TableView self.tableView.reloadData() // 如果有completion回调,在这里调用 // completion() }
3. 修正删除逻辑
根据点击的是Comment还是Reply,构建正确的Firebase路径执行删除,并同步更新TableView:
let selectedItem = self.comments[indexPath.row] if let comment = selectedItem as? Comment { // 1. 删除该评论下的所有回复 let repliesRef = db.collection(comment.postCategory!).document(comment.postDocID!).collection("comments").document(comment.docID!).collection("replies") repliesRef.getDocuments { snapshot, error in guard let snapshot = snapshot, error == nil else { print(error!) return } for doc in snapshot.documents { doc.reference.delete { error in if let error = error { print("删除回复失败:\(error)") } } } } // 2. 删除评论本身 let commentRef = db.collection(comment.postCategory!).document(comment.postDocID!).collection("comments").document(comment.docID!) commentRef.delete { error in if let error = error { print("删除评论失败:\(error)") } else { // 从数组移除并刷新TableView self.comments.remove(at: indexPath.row) self.tableView.deleteRows(at: [indexPath], with: .fade) } } } else if let reply = selectedItem as? Reply { // 删除回复本身 let replyRef = db.collection(reply.postCategory!).document(reply.postDocID!).collection("comments").document(reply.parentCommentDocID!).collection("replies").document(reply.docID!) replyRef.delete { error in if let error = error { print("删除回复失败:\(error)") } else { self.comments.remove(at: indexPath.row) self.tableView.deleteRows(at: [indexPath], with: .fade) } } }
内容的提问来源于stack exchange,提问作者EAO123
相关产品推荐
相关产品推荐

