【问题标题】:How to get messages ordered by timestamp如何获取按时间戳排序的消息
【发布时间】:2018-02-28 03:42:34
【问题描述】:

我想按创建日期(即时间戳)获取所有消息。

我的数据结构是这样的:

messages
  XRJONcahNUgeNrfkH3cmITJt3409 (auto uid of owner - user)
    -KoOSxA2Iajk3kv20U_p (automatic uid generated by Firebase)
      message: "Hi"
      senderId: "X8Oxg5J9Imb12C1iYBXJT9P48909"
      senderName: "Dave"
      timestamp: 1505813320526 (automatic timestamp)
    -GdOSxR2Iajk3kv20U_p --- I NEED TO SORT THESE UIDS
      message: "Hello"
      senderId: "G7Oxg5J9Imb12C1iYBXJT9P48909"
      senderName: "Frank"
      timestamp: 1505813321024 (automatic timestamp)

我收到所有这样的消息:

database.child("messages").child(ownersId).observeSingleEvent(of: .value, with: { (snapshot) in
            print(snapshot)
            if let messagesDict = snapshot.value as? [String:AnyObject] {
                for (_,message) in messagesDict {
                    self.messages.append((message["message"] as? String)!)
                    self.users.append((message["senderName"] as? String)!)
                    self.timestamps.append((message["timestamp"] as? IntMax)!)
                }
            }
            completionHandler(true)

        }) { (error) in
            print(error.localizedDescription)
            completionHandler(false)
        }

所以问题是,我怎样才能让所有消息从最旧到最新排序?我不知道在这种特定情况下如何使用排序方法(queryOrderedByKey()、queryOrderedByValue() 或 queryOrdered(byChild: "timestamp")。Firebase 以随机顺序向我发送数据(我不知道它是否是随机的,但它是不按日期排序)。

【问题讨论】:

    标签: ios swift firebase firebase-realtime-database


    【解决方案1】:

    正如 Rashwan 所说,您需要致电 queryOrderedByChild() 才能以正确的顺序退货。然后你循环 snapshot.children 以确保你也以正确的顺序处理它们。

    所以:

    database.child("messages").queryOrdered(byChild: "timestamp").observe(.value, with: { snapshot in
        for child in snapshot.children.allObjects as! [DataSnapshot] {
            print("\(child.key)")
        }
    
        completionHandler(true)
    })
    

    回调中的重要一点是不要将整个快照转换为字典,因为字典不会维护项目的顺序。

    【讨论】:

    • 谢谢,但这不起作用。 FIRDataSnapshot 现在只有 DataSnapshot(而 println 是 print),但即使我改变它,它也会给我 Type "DataSnapshot" has no subscript members on each child。
    • 很抱歉。我用我刚刚在 xcode 中运行的一些代码更新了答案。它打印-KoOSxA2Iajk3kv20U_p -GdOSxR2Iajk3kv20U_p,以便以正确的顺序检索/迭代节点。
    • 谢谢,但我认为这仍然不是答案。请看我更新的问题。编辑:我试过了,这不是一个正确的答案。我有消息,下面是参考用户的 uid,之后是我需要排序的最终 uid。
    • 我的代码打印KoOSxA2Iajk3kv20U_p -GdOSxR2Iajk3kv20U_p。这不是正确的顺序吗?据我所知:KoOSxA2Iajk3kv20U_pGdOSxR2Iajk3kv20U_p 早。
    • 好的,看来可以了。我只需要添加孩子(ownersId)。但现在我需要从 DataSnapshot 中获取数据。
    【解决方案2】:

    您使用database.queryOrdered 而不是database.child,如下所示:

    database.queryOrdered(byChild: "messages"). observeSingleEvent(.value, with: { (snapshot) in
        print("\(snapshot.value)")
    }
    

    但您也可以像今天一样获取数据,然后对列表进行排序self.timestamps

    self.timestamps.sorted(by: { $0 > $1 })
    

    更新:
    创建一个模型并将您的属性附加到该模型,然后附加到一个列表并在此之后对该列表进行排序。像这样:

    struct Model {
        let message: String?
        let senderId: String?
        let senderName: String?
        let timestamp: IntMax
    
        init(message: String?, senderId: String?, senderName: String?, timestamp: IntMax?) {
            self.message = message
            self.senderId = senderId
            self.senderName = senderName
            self.timestamp = timestamp
        }
    }
    
    var models = [Model]()
    models.sorted(by: { $0.0.timestamp > $0.1.timestamp })
    

    更新 2:
    要添加模型,请查看以下代码示例:

    database.child("messages").child(ownersId).observeSingleEvent(of: .value, with: { (snapshot) in
        print(snapshot)
        var models = [Model]()
        if let messagesDict = snapshot.value as? [String:AnyObject] {
            for (_,message) in messagesDict {
                if let message = message["message"] as? String, let senderName = message["senderName"] as? String, let timestamp = message["timestamp"] as? IntMax, let senderId = message["senderId"] as? String {
                    let model = Model(message: message, senderId: senderId, senderName: senderName, timestamp: timestamp)
                    models.append(model)
                }
            }
            models.sorted(by: { $0.0.timestamp > $0.1.timestamp })
        }
        completionHandler(true)
    
    }) { (error) in
        print(error.localizedDescription)
        completionHandler(false)
    }
    

    【讨论】:

    • 谢谢,但这也不起作用。我想我错误地描述了我的问题。我更新了我的问题。
    • @Boomerange,查看更新后的帖子。我认为这是你需要的东西。
    • 如何在该循环中附加到模型?
    • 谢谢,但这表明我无法在 message["senderName"] 上使用 'String' 类型的索引来下标 'String' 类型的值
    • 你们都帮了我很多。我会接受弗兰克斯的回答,因为我认为他回答了我的问题。但是因为你,我重构了我的代码并学到了一些新东西。谢谢你,拉什万。
    猜你喜欢
    • 2020-11-18
    • 2012-06-23
    • 2020-07-05
    • 2018-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-10
    • 1970-01-01
    相关资源
    最近更新 更多