2017-05-24 61 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的火力點。它可以用來排序/查詢

另外,作爲一個附註,並不是依靠節點的創建日期(通過鍵)來保持排序,而是考慮在節點中讀取時利用時間戳。 (按:時間戳)。這將保證即使消息被改變或者鍵被修改,它們也總是處於正確的順序。