无法从 Firebase 实时数据库读取数据

时间:2021-07-09 10:12:29

标签: swift firebase firebase-realtime-database

我已将评论存储在 firebase 实时数据库中的帖子下。我遇到的问题是,当我尝试从 firebase 解析出数据时,我收到一个错误,提示在展开 Optional 值时意外发现 nil。因此,例如,如果我尝试在度下存储存储的数据,则会出现此 nil 错误。但是当我打印“评论”而不是“学位”时,我成功地获取了数据。我的数据库结构是这样的。

Firebase database

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

2 个答案:

答案 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)")
        }
    })
}