繁体   English   中英

Firebase排序

[英]Firebase Sorting

基本上,我在Firebase上有一个应用程序。 事实是,当Firebase对数据进行排序而不是按时间顺序排序时,它将对数据进行混淆。

当我上网搜索原因时,发现这是因为我使用的是snapshot.value而不是snapshot.children。

但是,我不确定如何相应地更改代码,有人可以帮忙吗?

这是代码:

func retrieveChatLog() {

        FIRDatabase.database().reference().child("chats").child(chatID).observe(.value, with: {(snapshot) in

        let chats = snapshot.value as! [String : AnyObject]

        self.messages.removeAll()

        for (_, value) in chats {

            if let sender = value["sender"], let message = value["message"], let senderID = value["senderUID"], let date = value["date"] {

                let messageToShow = Message()

                messageToShow.message = message as! String

                messageToShow.sender = sender as! String

                messageToShow.senderUID = senderID as! String

                let formatter = DateFormatter()

                formatter.dateFormat = "dd.MM.yyyy"

                let curDate = formatter.date(from: date as! String)

                messageToShow.date = curDate as! Date

                if messageToShow.senderUID != "" {
                    self.messages.append(messageToShow)
                }
            }
        }
        self.tableView.reloadData()
    })
    FIRDatabase.database().reference().removeAllObservers()
}        

更改此行FIRDatabase.database().reference().child("chats").child(chatID).observe(.value, with: {(snapshot) in...

对此FIRDatabase.database().reference().child("chats").child(chatID).observe(.childAdded, with: {(snapshot) in

问题不是因为您使用了snapshot.value。 您可以使用.value或.childAdded。 问题是,如果您使用.value,则您不希望将快照转换为字典,因为字典不会保留顺序。 相反,您将要强制转换为数组以保留顺序。 这是解决此问题的一种方法:

FIRDatabase.database().reference().child("chats").child(chatID).observe(.value, with: {(snapshot) in
    let chats = snapshot.children.allObjects as! [FIRDataSnapshot]
    self.messages.removeAll()

    for chat in chats {
        if let value = chat.value as? [String: AnyObject] {
            if let sender = value["sender"], let message = value["message"], let senderID = value["senderUID"], let date = value["date"] {

                let messageToShow = Message()
                messageToShow.message = message as! String
                messageToShow.sender = sender as! String
                messageToShow.senderUID = senderID as! String
                let formatter = DateFormatter()
                formatter.dateFormat = "dd.MM.yyyy"
                let curDate = formatter.date(from: date as! String)
                messageToShow.date = curDate as! Date
                if messageToShow.senderUID != "" {
                    self.messages.append(messageToShow)
                }
            }
        }
    }
    self.tableView.reloadData()
})
FIRDatabase.database().reference().removeAllObservers()

}

答案是可以接受的,但我想提供另一个可能更紧凑,更可扩展的解决方案。

它从一个类来保存消息。 在这种情况下,我只保留firebase密钥和时间戳,但可以轻松添加其他var。 您会注意到从Firebase以相同的格式dd.mm.yy读取的时间戳var。 如果需要,这对于排序很有用。 还要注意,如果要显示格式正确的mm / dd / yyyy格式,则可以通过formattedDate计算属性使用它。

messagesArray是MessageClass对象的数组,例如,可以用作tableView的数据源。

最后,loadMessages函数加载所有消息。 如另一个答案中所述,将快照转换为字典将失去顺序保证。 但是,如果我们直接遍历快照,则顺序保持不变。

class MessageClass {
    var timestamp: String
    var fbKey: String
    var formattedDate: String {
        let formatter = DateFormatter()
        formatter.dateFormat = "dd.MM.yyyy"
        let d = formatter.date(from: timestamp)

        let outputFormattter = DateFormatter()
        outputFormattter.dateFormat = "MM/dd/yyyy"
        let finalDate = outputFormattter.string(from: d!)

        return finalDate
    }

    init(withSnap: DataSnapshot ) {
        let snapDict = withSnap.value as! [String: AnyObject]
        self.timestamp = snapDict["timestamp"] as! String
        self.fbKey = withSnap.key
    }
}

var messagesArray = [MessageClass]()

func doButton0Action() {

    let messagesRef = self.ref.child("messages")
    messagesRef.observe(.value, with: { snapshot in
        for child in snapshot.children {
            let snap = child as! DataSnapshot
            let m = MessageClass(withSnap: snap)
            self.messagesArray.append(m)
        }
        for msg in self.messagesArray { //test code to print the array once loaded
            print("key: \(msg.fbKey)  date: \(msg.formattedDate)")
        }
    })
 }

这段代码很冗长,可以被浓缩,但是可读性很强。 (它也需要防护措施和错误检查)。

我强烈建议您将时间戳记存储在

YYYYMMDDHHMMSS

在firebase中格式化。 它适合于排序/查询

另外,作为旁注,不要依赖于节点的创建日期(通过键)来保持顺序,而是在使用.order(by:timestamp)读取节点时考虑利用时间戳。 这样可以确保即使消息更改或密钥被更改,它们也始终处于正确的顺序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM