我有一个firebase查询,用于观察帖子中的数据。
func fetchPosts () {
let query = ref.queryOrdered(byChild: "timestamp").queryLimited(toFirst: 10)
query.observe(.value) { (snapshot) in
for child in snapshot.children.allObjects as! [DataSnapshot] {
if let value = child.value as? NSDictionary {
let post = Post()
let poster = value["poster"] as? String ?? "Name not found"
let post_content = value["post"] as? String ?? "Content not found"
let post_reveals = value["Reveals"] as? String ?? "Reveals not found"
post.post_words = post_content
post.poster = poster
post.Reveals = post_reveals
self.postList.append(post)
DispatchQueue.main.async { self.tableView.reloadData() }
//make this for when child is added but so that it also shows psots already there something like query.observre event type of
}
}
但是,当用户发布内容时,会创建一个包含数据的多个单元格。例如,如果我发布“hello”,就会出现两张新牌,上面写着你好。但是,当我退出视图并调用fetch posts函数时,它会显示正确的单元格数量。此外,当我从数据库中删除帖子时,它还会添加一个新单元格并创建它的两个副本,直到我重新加载视图,然后它会显示数据库中的正确数据。
我怀疑这与observe(.value)有关,因为它可能从数据库中获取帖子,每次数据库更改时都会创建一个新数组。因此,当我添加一个新帖子时,它正在添加一个数组,用于添加帖子并且它现在存在于数据库中,当我刷新视图时,它只是直接从数据库收集数据。
此外,有时会显示正确数量的单元格,有时会出现多个随机帖子实例,无论我是否刚刚添加它们。
如何更改我的查询以便它最初加载数据库中的所有帖子,并且当添加一些帖子时,它只创建一个新单元而不是两个?
编辑:似乎发生的逻辑是,当函数加载时,它会调用fetchPosts()来获取所有帖子。然后,当某些内容添加到数据库时,它会再次调用fetchPosts()并将新数据添加到数组中,同时获取所有旧数据。再次。
答案 0 :(得分:0)
您认为.value
事件类型每次发生更改时都会返回整个数组,这是对的。你真正需要的是query.observe(.childAdded)
听众。这将获取单个帖子对象而不是整个数组。请在viewDidAppear
方法中调用此方法。
您可能还希望实现query.observe(.childRemoved)
侦听器以检测何时删除帖子。
另一种方法是在初始加载时调用observeSingleEvent(.value)
,然后添加一个监听器query.queryLimited(toLast: 1).observe(.childAdded)
来监听最新的帖子。
答案 1 :(得分:0)
使用Firebase将快照附加到阵列时,我总是会做的一件事是检查它是否存在。在你的情况下,我会添加
if !self.postList.contains(post) {
self.postList.append...
然而,为了使这项工作,你必须为我猜测的Post类做出一个相同的协议:
extension Post: Equatable { }
func ==(lhs: Post, rhs: Post) -> Bool {
return lhs.uid == rhs.uid
}