Firebase查询快照为零?

我正在创build一个简单的聊天应用来学习Swift和Firebase。 我有一个查询,检查聊天室的消息加载到一个tableView。 查询返回一个快照,但是我无法正确地存储和加载数据。 我从快照创build了一个字典,所以我可以得到个别的孩子值,但他们返回零:

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但应用程序命中返回并停止执行代码块的其余部分。 如何正确访问发件人,文本和时间戳记元素,以便我可以将它们设置为variables并将它们存储在我的表格的数组中?

任何帮助将不胜感激。 我一直坚持这一段时间,我可以用另一双眼睛!

谢谢!!

附加信息:

查询:

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" : "tester2@test.com", "username" : "tester2" }, "eGTYRSo81JefgasYLRHUFHUTnEC3" : { "email" : "test@test.com", "username" : "tester" } } } 

我不认为你想要一个ChildAdded处理程序,所以我去一个observeSingleEvent例子,因为你想在没有触发器的情况下查询数据库中的数据。 当您使用observeSingleEvent时,保持数据库同步非常重要。 我会build议使用下面的代码:

 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 } } }) 

正如皮皮克斯解释的那样,你的问题是你试图在比返回的数据高一级的地方访问单个的消息细节。

快照值为您提供聊天消息字典,其中顶级的密钥是聊天消息密钥。 要将返回的数据映射到一个消息数组,我将使用以下代码:

 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]对象)。

这是否解决了这个问题?

你的字典看起来像:

 ▿ 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 

第一个scheme

您需要在查询中添加.child(“ – KotqLUUucaRagTRt967”)。

要么

解决scheme二

你需要做这样的事情:

 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 } }) 

更新:

 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 } } }) 

注意

正如Frank van Puffelen所说,我用observe来代替observeSingleEvent ,这对于.childAdded来说是一个不常见的组合。