【问题标题】:Firebase snapshots in wrong orderFirebase 快照顺序错误
【发布时间】:2016-12-19 13:14:31
【问题描述】:

我尝试将存储在 firebase 上的帖子加载到我的 tableView 中。我使用 .childAdded 函数按照发布的顺序(从前到后)获取帖子。首先它似乎工作,但现在它不再工作了,我不知道为什么。所以我在帖子中添加了一个时间戳并使用了 queryOrderedByChild("timestamp")。仍然是错误的顺序!这是我的代码:

posts.removeAll()
    let ref = FIRDatabase.database().reference()

    ref.child("Posts").queryOrderedByChild("timestamp").observeEventType(.ChildAdded, withBlock: { (snapshot:FIRDataSnapshot) in

        print(snapshot.value!["timestamp"] as! Int)
        if snapshot.value == nil {
            return
        }
        let post = Post()
        post.title = snapshot.value!["Title"] as? String
        post.postType = snapshot.value!["postType"] as? Int
        post.postDescription = snapshot.value!["Description"] as? String

        if post.postType == 2 {
            post.imageAURL = snapshot.value!["imageAURL"] as? String
            post.imageBURL = snapshot.value!["imageBURL"] as? String
        }else if post.postType == 3 {
            post.imageAURL = snapshot.value!["imageAURL"] as? String
            post.imageBURL = snapshot.value!["imageBURL"] as? String
            post.imageCURL = snapshot.value!["imageCURL"] as? String
        }


        let createdByID = snapshot.value!["createdBy"] as! String
        var username = String()
        let usernameRef = FIRDatabase.database().reference().child("users").child(createdByID)
        usernameRef.observeSingleEventOfType(.Value, withBlock: { (snapshot:FIRDataSnapshot) in

            username = snapshot.value!["username"] as! String
            post.createdBy = username
            self.posts.append(post)
            self.tableView.reloadData()
            }, withCancelBlock: nil)




            dispatch_async(dispatch_get_main_queue(), {

                self.tableView.reloadData()
            })


        }, withCancelBlock: nil)


}

查询开头的时间戳值打印出来:

1471008028
1471007899
1471007928
1471007979

如您所见,第一个 Int 是最高的,接下来的三个按升序正确排序,但为什么最高的在前而不是最后?我不知道它是否与它有任何关系,但代码在 viewDidLoad 内部调用的函数内。

【问题讨论】:

  • 我发布了来自不同用户帐户的帖子。我刚刚注意到,当前登录的用户的帖子总是最先加载的,但是为什么呢?意味着如果我以其他用户身份登录并再次启动模拟器,则顺序会更改,但 .ChildAdded 函数不应该关心登录的用户,因为它只会加载所有帖子,无论是谁发布的?
  • 这已被问及回答before
  • 我猜这个答案有点过时了,如果我错了,请纠正我。 swift中也没有示例,所以如果有人在swift中有一些解决方案或者可以编辑我的代码以便按照它应该的方式工作,那就太好了
  • 我也不明白为什么按时间戳排序似乎不起作用
  • 能否请您使用 Firebase 结构的 sn-p 作为文本更新您的问题,不要使用图像。

标签: ios database swift firebase firebase-realtime-database


【解决方案1】:

现有的answer 解释了为什么 Firebase JavaScript child_added 事件会乱序发生。它仍然适用,这就是您的快照以意外顺序交付的原因。

我知道这可能看起来很奇怪,但这实际上是预期的行为。

为了保证本地事件可以在不先与服务器通信的情况下立即触发,Firebase 不保证始终按排序顺序调用 child_added 事件。

要将收到的快照按正确顺序排列,您需要快照随附的前一个兄弟键(在引用的答案中称为prevChildName)。要获取之前的兄弟键,需要使用observeEventType:andPreviousSiblingKeyWithBlock:

observeEventType:andPreviousSiblingKeyWithBlock: 的 Firebase 文档没有明确说明应该如何使用前一个兄弟键来排列接收到的快照。

出于示例的目的,要将快照存储和排序到数组中,您需要对每个收到的快照执行以下操作:

  • 如果接收到的快照的前一个兄弟键为空,则将其添加到数组的头部;
  • 否则,在数组中找到key 等于前一个兄弟键(伴随接收到的快照)的快照,并将接收到的快照插入到找到的快照之后的数组中;
  • 如果没有具有前一个兄弟键的快照,则将接收到的快照添加到数组的尾部。

【讨论】:

  • 目前我没有时间尝试该解决方案,但我非常感谢您的回答,我将其标记为正确答案,因为我认为这应该可行!非常感谢!仍然我不明白为什么带有时间戳的 orderedByChild 不起作用?!
  • 这很痛苦,我知道。它就是这样——没有任何保证。如果您查看 Firebase 的 AngularFire2 源代码,您会发现他们使用基于 reduce 的机制来解释它。
  • 那么你知道为什么使用时间戳和orderedByChild 不起作用吗?就我阅读文档而言,它应该按升序对快照进行排序,对吗?为什么它不起作用?
  • 我刚刚发现了一些东西。我的应用程序曾经从登录用户的个人资料页面开始,该页面会加载所有用户的帖子。如果我注释掉用户帖子的加载并切换到此视图(调用我发布的代码的视图),一切正常。只有当我之前加载用户的帖子时,顺序是错误的,只有用户自己的帖子是错误的。那么这与我已经加载这些帖子的事实有什么关系吗?
猜你喜欢
  • 1970-01-01
  • 2023-03-18
  • 2019-07-28
  • 2018-11-26
  • 1970-01-01
  • 1970-01-01
  • 2017-03-26
  • 1970-01-01
  • 2021-11-23
相关资源
最近更新 更多