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

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 }
    }

问题根源

  1. 全局引用被覆盖:循环遍历cPosts和rPosts时,全局变量ref和repRef会被最后一次循环的集合引用覆盖,导致删除时使用错误的Firebase集合路径。
  2. 缺少关键路径信息:Comment和Reply模型仅保存自身的docID,未记录所属的帖子分类、帖子文档ID,删除时无法定位到正确的文档位置。
  3. 类型区分缺失: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:30:51