[英]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.