2017-05-24 53 views
0

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

当我上网搜索原因时,发现这是因为我使用的是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() 
}   

回答

0

的问题是不是因为你用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() 

}

+0

它给了行上的SIGABRT,其中snapshot.value被转换为[FIRDataSnapshot] –

+0

我的不好!它应该说有snapshot.children。allObjects,而不是价值。现在应该修复。 –

+0

我得到了另一个SIGABRT,但这次它说'无法将类型'_NSCFConstantString'的值转换为'NSDictionary',但是在说chat.value为!的行上! [String:AnyObject] –

0

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

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

0

有一个公认的答案,但我想提供另一种解决方案可能是有点更严格和更可扩展。

它从一个持有消息的类开始。在这种情况下,我只保留了Firebase密钥和时间戳,但可以轻松添加其他变量。您会注意到以相同格式从Firebase中读取的时间戳var:dd.mm.yy.如果需要,这将对分类很有用。另请注意,如果您想要显示格式良好的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的火力点。它可以用来排序/查询

另外,作为一个附注,并不是依靠节点的创建日期(通过键)来保持排序,而是考虑在节点中读取时利用时间戳。 (按:时间戳)。这将保证即使消息被改变或者键被修改,它们也总是处于正确的顺序。