点击点赞按钮后Feed帖子消失的Firestore技术问题排查
点赞后Feed帖子消失的问题排查与解决
问题场景
使用Firestore快照监听器加载动态Feed,点击点赞按钮更新帖子点赞数后,目标帖子会从Feed中消失,fetchUserPosts()输出调试信息显示数据库中无帖子,但Firestore后台的点赞数确实已成功增加。
相关代码
加载Feed帖子的函数
func fetchPosts() { let query = COLLECTION_POSTS .order(by: "timestamp", descending: true) query.addSnapshotListener { snapshot, _ in guard let changes = snapshot?.documentChanges.filter({$0.type == .added}) else {return} self.posts = changes.compactMap { do { return try $0.document.data(as: Post.self) } catch { print("Error converting Firestore document to Post object: \(error)") return nil } } self.fetchUserPosts() } }
点赞更新函数
func likePost(post: Post) { guard let uid = Auth.auth().currentUser?.uid else { return } guard let postId = post.id else { return } let userLikesRef = Firestore.firestore().collection("users").document(uid).collection("user-likes") Firestore.firestore().collection("posts").document(postId) .updateData(["likes" : post.likes + 1]) { _ in userLikesRef.document(postId).setData([:]) { _ in self.isLiked = true } } }
问题原因
- 快照监听器仅处理
.added变更:当点赞更新likes字段时,Firestore触发的是.modified类型的文档变更,但你的代码只过滤了.added类型的变更,此时changes为空数组,self.posts被直接赋值为空,导致帖子消失。 fetchUserPosts()可能覆盖数据:每次快照触发都调用该函数,如果它的逻辑是直接替换self.posts数组,会进一步清空Feed数据。
解决方案
1. 修改快照监听器,处理所有变更类型
不要直接替换整个posts数组,而是根据变更类型更新现有数组:
func fetchPosts() { let query = COLLECTION_POSTS .order(by: "timestamp", descending: true) query.addSnapshotListener { snapshot, error in guard let snapshot = snapshot else { print("Error fetching posts: \(error?.localizedDescription ?? "Unknown error")") return } for change in snapshot.documentChanges { do { let updatedPost = try change.document.data(as: Post.self) switch change.type { case .added: // 避免重复添加,保持时间戳降序 if !self.posts.contains(where: { $0.id == updatedPost.id }) { self.posts.append(updatedPost) self.posts.sort { $0.timestamp > $1.timestamp } } case .modified: // 找到对应帖子并更新数据 if let index = self.posts.firstIndex(where: { $0.id == updatedPost.id }) { self.posts[index] = updatedPost } case .removed: // 移除已删除的帖子 self.posts.removeAll { $0.id == updatedPost.id } } } catch { print("Error converting Firestore document to Post object: \(error)") } } // 若fetchUserPosts()是加载用户自有帖子,需改为合并逻辑而非替换 // self.fetchUserPosts() } }
2. 优化点赞逻辑(可选)
点赞后可以先更新本地模型,提升用户体验,再等待Firestore回调确认:
func likePost(post: Post) { guard let uid = Auth.auth().currentUser?.uid else { return } guard let postId = post.id else { return } let userLikesRef = Firestore.firestore().collection("users").document(uid).collection("user-likes") // 先更新本地模型 if let index = self.posts.firstIndex(where: { $0.id == postId }) { var updatedPost = post updatedPost.likes += 1 self.posts[index] = updatedPost self.isLiked = true } Firestore.firestore().collection("posts").document(postId) .updateData(["likes" : post.likes + 1]) { error in if let error = error { // 网络失败时回滚本地数据 print("Failed to update likes: \(error)") if let index = self.posts.firstIndex(where: { $0.id == postId }) { self.posts[index] = post self.isLiked = false } return } userLikesRef.document(postId).setData([:]) } }
3. 检查fetchUserPosts()逻辑
确认该函数的作用,如果是加载用户自己的帖子,需要改为合并到现有posts数组,而不是直接替换,避免覆盖Feed数据。
内容的提问来源于stack exchange,提问作者user20072735
相关产品推荐
相关产品推荐

