我已将评论存储在 firebase 实时数据库中的帖子下。我遇到的问题是,当我尝试从 firebase 解析出数据时,我收到一个错误,提示在展开 Optional 值时意外发现 nil。因此,例如,如果我尝试在度下存储存储的数据,则会出现此 nil 错误。但是当我打印“评论”而不是“学位”时,我成功地获取了数据。我的数据库结构是这样的。
func obeserveComments() {
// get auto-id of post
let commentKey = self.keyFound
let postRef = Database.database().reference().child("posts").child(commentKey)
var tempComments = [Comments]()
postRef.observe(.value, with: {(snapshot) in
if let dict = snapshot.value as? [String:Any] {
if let comments = dict["comments"] as? [String:Any] {
let degree = comments["reply degree"] as! String
// let name = comments["reply name"] as! String
// let text = comments["reply text"] as! String
// let university = comments["reply university"] as! String
// let photoURL = comments["reply url"] as! String
// let url = URL(string: photoURL)
// let timestamp = comments["timestamp"] as! Double
print(degree)
}
}
})
}
答案 0 :(得分:1)
这是因为 firebase 正在像这样返回您的数据
{
"MAKFW244kdL)Cw;1": [Array of data],
"LOPSw!35pa3flAL4": [Array of data],
"ALV34VR4_A6Vn1a": [Array of data]
}
因此将您对 snapshot.value 的初始转换更改为:
if let dict = snapshot.value as? [String: [String: Any]]
然后像这样循环遍历新字典:
for objectJson in dict.values {
if let comments = objectJson["comments"] as? [String: [String: Any]] {
for commentJson in comments.values {
let degree = commentJson["reply_degree"] as? String
}
}
}
再次通读您的帖子并注意到您尝试使用密钥直接访问 comments
,您首先需要提供 PostId
。然后就可以用上面的代码循环遍历对象了
let postRef = Database.database().reference().child("posts").child(postID)
或者,我相信您可以通过执行以下操作将评论作为普通列表返回:
let postRef = Database.database().reference().child("posts").child("\(postID)/{id}")
答案 1 :(得分:1)
@aytroncb 的回答是一个很好的答案,我更愿意尽可能长时间地将 Firebase 数据保留为“Firebase”。换句话说,转换到字典会失去排序并找到这样的代码
[String: [String: [String: Any]]]
很难阅读。
我更喜欢
let snap = snapshot.childSnapshot("comments") //snap becomes a DataSnapshot
所以我的解决方案维护顺序并利用 .childSnapshot 将数据保留在 DataSnapshot 形式中。
func readPostComments() {
let postRef = self.ref.child("posts") //self.ref points to my firebase
postRef.observeSingleEvent(of: .value, with: { snapshot in
let allPosts = snapshot.children.allObjects as! [DataSnapshot]
for postSnap in allPosts {
print("postId: \(postSnap.key)")
let commentsSnap = postSnap.childSnapshot(forPath: "comments") //will be a DataSnapshot
let allComments = commentsSnap.children.allObjects as! [DataSnapshot]
for commentSnap in allComments {
print(" commentId: \(commentSnap.key)")
let replyDegree = commentSnap.childSnapshot(forPath: "reply_degree").value as? String ?? "No Degree"
let replyName = commentSnap.childSnapshot(forPath: "reply_name").value as? String ?? "No Name"
print(" degree: \(replyDegree) by: \(replyName)")
}
}
})
}
编辑
对于单个帖子,删除读取并遍历所有帖子的代码的顶部。
func readCommentsForOnePost() {
let postRef = self.ref.child("posts")
let postCommentRef = postRef.child("post_0")
postCommentRef.observeSingleEvent(of: .value, with: { snapshot in
print("postId: \(snapshot.key)")
let commentsSnap = snapshot.childSnapshot(forPath: "comments") //will be a DataSnapshot
let allComments = commentsSnap.children.allObjects as! [DataSnapshot]
for commentSnap in allComments {
print(" commentId: \(commentSnap.key)")
let replyDegree = commentSnap.childSnapshot(forPath: "reply_degree").value as? String ?? "No Degree"
let replyName = commentSnap.childSnapshot(forPath: "reply_name").value as? String ?? "No Name"
print(" degree: \(replyDegree) by: \(replyName)")
}
})
}