创建自定义嵌套的tableview单元格

时间:2018-10-10 15:42:46

标签: swift firebase firebase-realtime-database

我想创建一个嵌套的评论部分。我正在使用Firebase作为数据库。在我的应用中,每个帖子都有一个评论部分。登录的用户可以发表评论,也可以评论他们的评论,从而产生嵌套效果。

因此,首先我显示对原始帖子的评论。我要做的是浏览每个评论,并检查该评论是否有评论,如果有评论,我希望它直接显示在该评论下方。就像Instagram或Facebook。

这是一个嵌套示例,在Firebase中看起来像一个JSON

{
  "author" : "patient0",
  "comments" : {
    "comment-487" : {
      "author" : "Doctor1",
      "comments" : {
        "comment-489" : {
          "content" : "Your internal capsule in your cerebrum was affected by the stroke",
          "id" : "comment-489",
          "reply_to" : "comment-487",
          "reply_to_type" : "comment"
        },
        "comment-490" : {
          "author" : "Doctor2",
                "content" : "Your internal capsule is closely associated with your basal ganglia structures",
          "id" : "comment-490",
          "reply_to" : "comment-487",
          "reply_to_type" : "comment"
        }
      },
      "content" : "I recently had a stroke",
      "id" : "comment-487",
      "post_id" : "post-1069",
      "reply_to" : "post-1069",
      "reply_to_type" : "post"
    },
    "comment-491" : {
      "author" : "MedStudent",
      "comments" : {
        "c_1531642274921" : {
          "content" : "Wow! I wonder what cranial nerves were affected due to the hemorrhage",
          "id" : "c_1531642274921",
          "post_id" : "post-1069",
          "pub_time" : 1531642274922,
          "reply_to" : "comment-491",
          "reply_to_type" : "comment"
        }
      },
      "content" : "The hemorrhage was by the pons and cranial nerve 3 is by the pons, maybe the patient lost the ability to accommodate their eye sight and keep their eyes open.",
      "id" : "comment-491",
      "num_likes" : 0,
      "post_id" : "post-1069",
      "reply_to" : "post-1069",
      "reply_to_type" : "post"
    }
  },
  "content" : "I have a headache",
  "id" : "post-1069",
  "num_comments" : 5,
  "title" : "I have a headache, should I go to the hospital",
}

到目前为止,我已经可以打印出初始注释(这些注释直接发送到帖子中了)

func loadComments(){
Database.database().reference().child("main").child("posts").child(postID!).child("comments").queryOrdered(byChild: "id").observeSingleEvent(of: .value, with: { (snapshot:DataSnapshot) in

            if let postsDictionary = snapshot .value as? [String: AnyObject] {


                  for testingkey in postsDictionary.keys {

                    Database.database().reference().child("main").child("posts").child(self.postID!).child("comments").child(testingkey).child("comments").queryOrdered(byChild: "post_id").observeSingleEvent(of: .value, with: { (snapshot:DataSnapshot) in

                         if let postsDictionary = snapshot .value as? [String: AnyObject] {

                            for post in postsDictionary {

                            }
                             DispatchQueue.main.async(execute: {
                            self.TableView.reloadData()
                                })
                        }

                    })
                }
                for post in postsDictionary {
                    //main comments
                    self.Comments.add(post.value)

                }
                 DispatchQueue.main.async(execute: {
                self.TableView.reloadData()
                })

            }
      })
}

我只是不知道如何浏览每个帖子,以查看是否有与之相关的评论。另外,如果有与原始评论关联的评论,我希望它在自定义单元格中打印出来。

3 个答案:

答案 0 :(得分:1)

我将创建一个classstruct进行评论,并将评论数组作为属性。

class Comment {
    let id: String
    let author: String
    var content: String
    var comments: [Comment]
} 

然后我将创建一个TopLevelComment类作为Comment的子类

class TopLevelComment: Comment {
    // Whatever special properties you want your top level comments to have
}

您现在可以通过简单地使用

来检查评论是在回复帖子还是评论
comment is TopLevelComment

然后,您应该适当地重组数据库,以便将其转换为Comment

对于您的tableView,我将为每个顶级注释使用一个表格视图,甚至可能为每个注释使用一个部分。

答案 1 :(得分:0)

您可以为注释元素创建一个元素。

var commentElements = [CustomStruct]()

创建自定义元素后,从Firebase中提取变量并保存。

if let postsDictionary = snapshot .value as? [String: AnyObject] {

guard let comment = postsDictionary["comments"] as? NSArray else { return }

for com in comment {
    guard let commentObject = com as? [String:Any] else { return }

    let id = commentObject["id"]
    let type = commentObject["reply_to_type"]
    let replyTo = commentObject["reply_to"]
    let content = commentObject["content"]

    let element = CustomStruct(id:id , type:type , ....)
    commentElements.append(element)

}

for post in postsDictionary {

}
 DispatchQueue.main.async(execute: {
self.TableView.reloadData()
    })
}

提取所有元素后,可以根据注释ID进行分组。然后可以在TableView中显示Section。对第一个元素"reply_to_type" : "post"

进行排序

答案 2 :(得分:0)

根据您的问题,我相信您在弄清楚如何将JSON解析为可用于显示帖子和评论的格式(或视图模型)时遇到困难。

您可以使用以下模型样本(如果需要,可以进行自己的修改或调整)来分析和整理您的帖子及其评论。

class Post {
    var author: String?
    var comments: [Post] = []
    var content: String?
    var id: String?
    var numComments: Int?
    var title: String?

    init(dict: [String: AnyObject]?) {
        author = dict?["author"] as? String
        content = dict?["content"] as? String
        id = dict?["id"] as? String
        numComments = dict?["num_comments"] as? Int
        title = dict?["title"] as? String

        if let commentsDict = dict?["comments"] as? [String: AnyObject] {
            // Sort the comments based on the id which seems to be appended to the comment key.
            let commentIds = commentsDict.keys.sorted()
            for id in commentIds {
                let comment = commentsDict[id] as? [String : AnyObject]
                comments.append(Post(dict: comment))
            }
        }
    }
}

用法:

//
// postDict is your dictionary object corresponding to one post.
//
// Assign your post's dictionary item to this variable.
//
var postDict: [String: AnyObject]?

// "Post" object which has recursive comments within up to any number of levels.
// Comments are also using the same model object. 
// If you want to use another, you can create one with the corresponding elements.
let post = Post(dict: postDict)

PS::JSON结构看起来不是唯一的结构。您可能需要对这种结构进行修改,以确保内容被整齐地映射。