2017-07-23 139 views
12

我正在創建一個簡單的聊天應用來學習Swift和Firebase。我有一個查詢來檢查聊天室的消息加載到tableView中。查詢返回快照,但我無法正確地存儲和加載數據。我創建從快照一本字典,所以我可以得到各個子值,但他們返回nil:在斷點處Firebase查詢快照爲零?

query.observeSingleEvent(of: .childAdded, with: { snapshot in 

      print(snapshot) 

      let indexPaths = self.messages.enumerated().map { 
       IndexPath(row: $0.0, section: 0) 
      } 

      guard let messagesDict = snapshot.value as? [String:AnyObject] else { return } 
      guard let sender = messagesDict["sender"] as? String else { return } 
      guard let text = messagesDict["text"] as? String else { return } 
      guard let timestamp = messagesDict["timestamp"] as? Int else { return } 

      let message = Message.init(key: snapshot.key, sender: sender as! String, text: text as! String, timestamp: timestamp) 

      self.messages.append(message) 

      self.tableView.reloadData() 
     }) 

po messagesDict返回數據:

▿ 1 element 
    ▿ 0 : 2 elements 
    - key : "-KotqLUUucaRagTRt967" 
    ▿ value : 3 elements 
     ▿ 0 : 2 elements 
     - key : sender 
     - value : eGTYRSo81JefgasYLRHUFHUTnEC3 
     ▿ 1 : 2 elements 
     - key : text 
     - value : test 
     ▿ 2 : 2 elements 
     - key : timestamp 
     - value : 1499914135546 

的應用到達下一個斷點哪裏我設置了guard let sender,但應用程序命中返回並停止執行代碼塊的其餘部分。如何正確訪問發件人,文本和時間戳記元素,以便我可以將它們設置爲變量並將它們存儲在我的表格的數組中?

任何幫助將不勝感激。我一直堅持這一段時間,我可以用另一雙眼睛!

謝謝!

附加信息:

查詢:

let query = rootRef.child("chat-messages/\(chatKey)")

數據庫結構:

{ 
    "chat-messages" : { 
    "-KotqKI4zF9cS5XMR9WU" : { 
     "-KotqLUUucaRagTRt967" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499914135546 
     } 
    }, 
    "-KotqvBoFFzOTY6Q1fO7" : { 
     "-KotqwGAJ85NuAp-Lh3Z" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499914290279 
     } 
    }, 
    "-KotsNgF0ou5MIDn2l5K" : { 
     "-KotsOSXw7OS_3xuXZgP" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499914671997 
     }, 
     "-KotsPqrCpipMLulNNFl" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test44", 
     "timestamp" : 1499914677715 
     } 
    }, 
    "-Kotsv1Vv19dEF2q7XQu" : { 
     "-KotsvYO9JvLY8gdTnA0" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499914811675 
     }, 
     "-KotsvxKXzIwbyvbwLPp" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499914813335 
     }, 
     "-Kotsw9vLiEf6KquU__e" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499914814205 
     }, 
     "-KotswHnzmfkEXih1O7y" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499914814709 
     }, 
     "-KotszHKBt254jZnUMAl" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test46456", 
     "timestamp" : 1499914826967 
     } 
    }, 
    "-KoyheS01YxWExSNxl_H" : { 
     "-Koyhf3G-FPEDrxQOcpU" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499995746607 
     } 
    }, 
    "-Koyjc_aBaF1kFE-8Bll" : { 
     "-Koyjd9PnO6sPOhS7P27" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499996263096 
     }, 
     "-KoyjdzSEi5twTVQMGOu" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499996266491 
     }, 
     "-Koyje2C9E524kV7nhLY" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1499996266730 
     } 
    }, 
    "-KpfUGw45F1FU2IrR87A" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1500746948396 
    }, 
    "-KpfUHQGuTDi4yZutS5K" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1500746950368 
    }, 
    "-KpfUHdSXeTzauATsDAP" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "test", 
     "timestamp" : 1500746951277 
    }, 
    "-Kpfia0fXsoqpRtIr1kU" : { 
     "sender" : "eGTYRSo81JefgasYLRHUFHUTnEC3", 
     "text" : "gerg", 
     "timestamp" : 1500750962815 
    } 
    }, 
    "chat-participants" : { 
    "-KotqKI4zF9cS5XMR9WU" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    }, 
    "-KotqvBoFFzOTY6Q1fO7" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    }, 
    "-KotsNgF0ou5MIDn2l5K" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    }, 
    "-Kotsv1Vv19dEF2q7XQu" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    }, 
    "-KoyheS01YxWExSNxl_H" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    }, 
    "-Koyjc_aBaF1kFE-8Bll" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    }, 
    "-KpfLBjQdPiX2kSrl1yF" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    } 
    }, 
    "chats" : { 
    "-KotqKI4zF9cS5XMR9WU" : { 
     "currentName" : "test", 
     "date" : 1499914130657 
    }, 
    "-KotqvBoFFzOTY6Q1fO7" : { 
     "currentName" : "test", 
     "date" : 1499914285904 
    }, 
    "-KotsNgF0ou5MIDn2l5K" : { 
     "currentName" : "test", 
     "date" : 1499914668844 
    }, 
    "-Kotsv1Vv19dEF2q7XQu" : { 
     "currentName" : "test", 
     "date" : 1499914809570 
    }, 
    "-KoyheS01YxWExSNxl_H" : { 
     "currentName" : "test", 
     "date" : 1499995744095 
    }, 
    "-Koyjc_aBaF1kFE-8Bll" : { 
     "currentName" : "test", 
     "date" : 1499996260740 
    }, 
    "-KpfLBjQdPiX2kSrl1yF" : { 
     "currentName" : "test3222", 
     "date" : 1500744567786 
    } 
    }, 
    "user-chats" : { 
    "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "-KotqKI4zF9cS5XMR9WU" : { 
     "chatKey" : "-KotqKI4zF9cS5XMR9WU", 
     "currentName" : "test" 
     }, 
     "-KotqvBoFFzOTY6Q1fO7" : { 
     "chatKey" : "-KotqvBoFFzOTY6Q1fO7", 
     "currentName" : "test" 
     }, 
     "-KotsNgF0ou5MIDn2l5K" : { 
     "chatKey" : "-KotsNgF0ou5MIDn2l5K", 
     "currentName" : "test" 
     }, 
     "-Kotsv1Vv19dEF2q7XQu" : { 
     "chatKey" : "-Kotsv1Vv19dEF2q7XQu", 
     "currentName" : "test" 
     }, 
     "-KoyheS01YxWExSNxl_H" : { 
     "chatKey" : "-KoyheS01YxWExSNxl_H", 
     "currentName" : "test" 
     }, 
     "-Koyjc_aBaF1kFE-8Bll" : { 
     "chatKey" : "-Koyjc_aBaF1kFE-8Bll", 
     "currentName" : "test" 
     }, 
     "-KpfLBjQdPiX2kSrl1yF" : { 
     "chatKey" : "-KpfLBjQdPiX2kSrl1yF", 
     "currentName" : "test3222" 
     } 
    } 
    }, 
    "user-friends" : { 
    "36HDn5XyxjMCcMluJJ9KPBOCDMm1" : { 
     "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "username" : "tester" 
     } 
    }, 
    "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "36HDn5XyxjMCcMluJJ9KPBOCDMm1" : { 
     "username" : "tester2" 
     } 
    } 
    }, 
    "user-invites" : { 
    "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "36HDn5XyxjMCcMluJJ9KPBOCDMm1" : { 
     "username" : "tester2" 
     } 
    } 
    }, 
    "users" : { 
    "36HDn5XyxjMCcMluJJ9KPBOCDMm1" : { 
     "email" : "[email protected]", 
     "username" : "tester2" 
    }, 
    "eGTYRSo81JefgasYLRHUFHUTnEC3" : { 
     "email" : "[email protected]", 
     "username" : "tester" 
    } 
    } 
} 
+0

您的查詢是什麼?和你的數據庫結構? – Pipiks

+0

感謝您的幫助!我編輯了問題以包含查詢和數據庫結構。 – winston

+0

@freeman我前幾天添加了一個建議的解決方案 - 解決問題還是有問題? – Yasir

回答

3

你的字典的樣子:

▿ 1 element 
    ▿ 0 : 2 elements 
    - key : "-KotqLUUucaRagTRt967" 
    ▿ value : 3 elements 
     ▿ 0 : 2 elements 
     - key : sender 
     - value : eGTYRSo81JefgasYLRHUFHUTnEC3 
     ▿ 1 : 2 elements 
     - key : text 
     - value : test 
     ▿ 2 : 2 elements 
     - key : timestamp 
     - value : 1499914135546 

但實際上它應該看起來像(如果你想獲得大辭典[ 「發件人」):

▿ 2 elements 
    ▿ 0 : 2 elements 
    - key : sender 
    - value : eGTYRSo81JefgasYLRHUFHUTnEC3 
    ▿ 1 : 2 elements 
    - key : text 
    - value : test 
    ▿ 2 : 2 elements 
    - key : timestamp 
    - value : 1499914135546 

解決方案一:

您需要在查詢中添加.child(「 - KotqLUUucaRagTRt967」)。

OR

解決方法二:

你需要做這樣的事情:

query.observe(.childAdded, with: { snapshot in 
    for child in snapshot.children { 
     guard let value = child.value as? NSDictionary else { 
      return 
     } 

     guard let sender = value["sender"] as? String else { 
      return 
     } 

     // You can user the sender 
    } 
}) 

UPDATE:

query.observe(.childAdded, with: { snapshot in 
    for child in snapshot.children.allObjects as! [FIRDataSnapshot] { 
     if let value = child.value as? [String:Any], let sender = value["sender"] as? String { 
      // You can user the sender 
     } 
    } 
}) 

注意

我更換observeSingleEvent觀察,爲弗蘭克麪包車Puffelen說,它是一種罕見的組合。childAdded

+0

謝謝!我收到錯誤'任何類型的值沒有成員值'。它在'value = child.value'上出錯。有任何想法嗎? – winston

+0

@freeman是否確保在'value = child.value'之前包含'guard let'? –

+0

@RajatKhare是的,它仍然在這條線上的錯誤'警衛讓價值= child.value爲? NSDictionary其他{return}'。 XCode建議將其更改爲'guard let value =(child as AnyObject).value as? NSDictionary其他{返回}'但是然後拋出錯誤'曖昧的使用價值' – winston

4

我不認爲你想要一個ChildAdded處理程序,所以我去一個observeSingleEvent示例,因爲你想在沒有觸發器的情況下從數據庫查詢數據。當您使用observeSingleEvent時,保持數據庫同步非常重要。我會建議使用下面的代碼:

query.keepSynched(true) //keeps data in sync with database, if you have data persistince on in your appDelegate 
query.observeSingleEvent(of: .value, with: { (snapshot) in //notice the changed here 
      print(snapshot) 
      //Since you want to loop again because there could be multiple 
      //messages in that chatroom which all have a unique ID, do this loop: 
      let enumerator = snapshot.children 
      while let rest = enumerator.nextObject() as? FIRDataSnapshot { 
       //this is 1 single message here 
       let values = rest.value as? NSDictionary 
       for (key, value) in values{ 
       print("Key: \(key), value: \(value)") 
       } 
       //lets say you want to check if there is a value with a key named "text": 
      let textUser = values?["text"] as? String ?? "No text found" 
       //providing a default value if there is no text. You could leave it empty, than it is nil (not recommend) 
       //Not only is this a lot more readable, I do not use force unwrapping so your app 
       //cannot cause an exception. 

       //Get more values from the dictionary as I did with textUser 
       //Initialize message than here. You will see you do not need to force unwrap anything :D 
       } 

      } 

     }) 
+0

「你和Pipiks結合了一個observeSingleEvent與一個ChildAdded,這兩個不會在一起」雖然這是一個不常見的組合,這些技術原因不能合併。 –

+0

同意,不明白爲什麼你不能結合單個事件和childAdded? – Yasir

+0

@Yasir我當然不知道,那就是爲什麼「我認爲??!」。從我閱讀的文檔中可以看出,每次添加新的子項時都會觸發childAdded。一個observeSingleEvent將讀取當時的數據。我認爲兩個人不會一起工作,但弗蘭克已經糾正了我,我會編輯這部分。 –

3

由於Pipiks解釋,你的問題是,你正試圖以比返回的數據更高一級訪問個人信息的詳細信息。

快照值爲您提供了聊天消息字典,其中頂級的鍵是聊天消息鍵。爲了您的返回數據映射到消息的數組,我會用下面的代碼:

query.observeSingleEvent(of: .childAdded, with: { snapshot in 

    guard let messagesDict = snapshot.value as? [String: AnyObject] else { return } 

    self.messages = messagesDict.flatMap({ (messageId: String, messageData: Any) -> Message? in 
     guard 
      let sender = messageData["sender"] as? String, 
      let text = messageData["text"] as? String, 
      let timestamp = messageData["timestamp"] as? Int, 
      let message = Message(key: messageKey, sender: sender, text: text, timestamp: timestamp) else { 
       return nil 
     } 
     return message 
    }) 

    self.tableView.reloadData() 
}) 

這樣做是你的地圖信息的字典Message對象的數組。

我已經使用flatMap過濾掉沒有發件人,文本或時間戳值的消息(因此flatMap返回一個[Message]對象)。

這是否解決了這個問題?

+0

我遺漏了indexPaths代碼,因爲它看起來不像它在任何地方使用:) – Yasir