SwiftUI Firebase聊天应用删除会话后对方打开崩溃问题求助
问题分析与解决方案
问题根源
当用户删除自己的聊天会话时,原删除逻辑仅从Thread文档的uid数组移除了自身ID,但未正确判断是否需要删除整个文档(deleteThreadIfNecessary传入的是移除前的Thread对象,导致判断失效)。此时聊天伙伴的客户端会收到一个uid数组仅包含自身ID的Thread,计算chatPartnerId时返回空字符串,调用fetchUser时传入空ID触发Firebase的FIRInvalidArgumentException错误。
修复步骤
1. 修正删除逻辑,确保无效Thread被彻底清理
修改删除流程,移除用户ID后获取最新的Thread数据,再判断是否需要删除文档:
func deleteThread(_ thread: Thread) async throws { guard let uid = Auth.auth().currentUser?.uid else { return } // 移除当前用户ID try await removeUserFromThread(thread, uid: uid) // 获取更新后的Thread文档 let updatedThreadDoc = try await THREADS.document(thread.id).getDocument() guard var updatedThread = try? updatedThreadDoc.data(as: Thread.self) else { return } // 当无参与者或只剩当前用户时删除文档 try await deleteThreadIfNecessary(updatedThread) } private func deleteThreadIfNecessary(_ thread: Thread) async throws { guard let currentUid = Auth.auth().currentUser?.uid else { return } let shouldDelete = thread.uid.isEmpty || (thread.uid.count == 1 && thread.uid.first == currentUid) if shouldDelete { try await THREADS.document(thread.id).delete() } }
2. 添加入口校验,避免无效Thread进入会话列表
在createNewThread方法中先检查chatPartnerId是否有效,为空则跳过插入:
func createNewThread(_ thread: Thread) async { guard !thread.chatPartnerId.isEmpty else { print("DEBUG: 无效会话,无聊天伙伴,跳过插入") return } do { var copy = thread copy.chatPartner = try await UserService().fetchUser(withUid: thread.chatPartnerId) self.threads.insert(copy, at: 0) } catch { print("DEBUG: 获取聊天伙伴失败,错误:\(error)") } }
3. 增强Thread模型的安全性
优化Thread模型的属性计算,添加有效性校验:
struct Thread: Identifiable, Hashable, Codable { // ... 原有属性 ... var chatPartnerId: String { guard let currentUid = Auth.auth().currentUser?.uid else { return "" } return uid.filter { $0 != currentUid }.first ?? "" } // 新增:判断是否有有效聊天伙伴 var hasValidChatPartner: Bool { return !chatPartnerId.isEmpty } }
之后可以用thread.hasValidChatPartner替代直接判断字符串是否为空,代码可读性更强。
4. 过滤流式获取的无效Thread
在streamThreads中提前过滤掉无有效聊天伙伴的Thread,避免后续处理出错:
func streamThreads() async { for await thread in service.streamThreads() { guard thread.hasValidChatPartner else { // 可选:自动清理Firestore中的无效Thread try? await service.deleteThread(thread) continue } await updateThreads(thread) } }
内容的提问来源于stack exchange,提问作者Buhle
相关产品推荐
相关产品推荐

