新Firebase数据导致TableView单元格闪烁(Firebase/iOS/Swift)

新Firebase数据导致TableView单元格闪烁(Firebase/iOS/Swift),ios,swift,uitableview,firebase,firebase-realtime-database,Ios,Swift,Uitableview,Firebase,Firebase Realtime Database,我的主要问题是如何消除闪烁,但我也只想知道我是否正确且最有效地处理非规范化的Firebase数据。我的方法接近正确吗 因此,我正在努力用非规范化的数据正确显示firebase数据库中的数据。我有帖子,然后评论与每个帖子相关。每次有人打开帖子的评论部分时,通过从viewcontroller切换到新的viewcontroller,它会获取帖子的唯一键(postKey),然后扫描与postCommentGroup中包含的postKey关联的评论组。评论组是postCommentGroup中每个post

我的主要问题是如何消除闪烁,但我也只想知道我是否正确且最有效地处理非规范化的Firebase数据。我的方法接近正确吗

因此,我正在努力用非规范化的数据正确显示firebase数据库中的数据。我有帖子,然后评论与每个帖子相关。每次有人打开帖子的评论部分时,通过从viewcontroller切换到新的viewcontroller,它会获取帖子的唯一键(postKey),然后扫描与postCommentGroup中包含的postKey关联的评论组。评论组是postCommentGroup中每个postKey的子级,它只是commentKey作为key,值为“true”,表示哪些评论与哪些帖子关联。这些评论在一个完全不同的分支中,因为我认为Firebase文档建议人们应该这样做

我基本上有3层嵌套的观察者

为了清晰起见,我在tableview中使用dequeuereusablecells回收单元格,我还有一个基本的延迟加载/图像缓存机制,可能也会干扰事情,但我在其他不太复杂的tableview上也有相同的机制,所以我不认为这是问题所在

由于我缺乏知识,除了经历这个循环之外,我不知道如何显示数据。我认为这个循环可能会导致闪烁,但我不知道如何让它加载数据。我尝试过其他各种方法,比如使用查询,但我一直无法让它工作

作为旁注,我试图加快查询数据的速度(我想这可能会对我有所帮助),但Swift的语法有了更新,Firebase也有了更新,这使得前面的示例有点难以理解

此外,我在Firebase网站或Github上的任何Firebase文档中都找不到以某种复杂方式正确使用非规范化数据的好例子。是否有人知道使用Swift 3.0和Firebase(最新版本,而不是旧版本)处理非规范化数据的好参考资料,无论是GitHub上的项目,还是博客,或者只是stackoverflow上最有用的帖子的集合

以下是firebase数据结构:


“评论”:{
“-KaEl8IRyIxRbYlGqyXC”:{
“description”:“1”,
“喜欢”:1,
“posted”:“-KaEfosaXYQzvPX5WggB”,
“profileImageUrl”:https://firebasestorage.googleapis.com",
“时间公告”:1484175742269,
“用户ID”:“9yhij9cBhJTmRTexsRfKRrnmDRQ2”,
“用户名”:“HouseOfPaine”
}
},
“后社区组”:{
“-KAEFOSAXYQZVPX5WGB”:{
“-KaEl8IRyIxRbYlGqyXC”:正确,
“-KaEl9HiPCmInE0aJH_f”:正确,
“-KaF817rRpAd2zSCeQ-M”:正确
},
“-KAF9ZXAEKTBETFGDB_5”:{
“-KaFEcXsSJyJwvlW1w2u”:真
},
“-KaJyENJFkYxCffctymL”:{
“-KaQYa0d08D7ZBirz5B4”:正确
}
},
“员额”:{
“-KAEFOSAXYQZVPX5WGB”:{
“标题”:“测试”,
“评论”:11,
“imageUrl”:https://firebasestorage.googleapis.com/",
“喜欢”:0,
“profileImageUrl”:https://firebasestorage.googleapis.com/",
“时间公告”:1484174347995,
“标题”:“测试”,
“用户”:“17lIDKNx6LgzQmaeQ2ING582zi43”,
“用户名”:“自由”
}

},
您的方法可能需要通过简化进行调整。我想提供所有的螺母和螺栓,所以它有点长,本身可以简化

虽然非规范化是正常的,但这不是一项要求,在某些情况下可能会增加额外的复杂性。结构postCommentGroup中的“层”似乎不需要

看起来您有一个包含帖子的视图控制器,还有一个视图控制器,当用户点击第一个控制器上的帖子时,该控制器会显示注释

您实际上只需要一个posts节点和comments节点

posts
   post_id_0
     title: "my post title"
     caption: "some caption"
     uid: "uid_0"
   post_id_1
     title: "another post title
     caption: "another caption
     uid: "uid_0"
以及引用帖子的评论节点

comments
   comment_0
     post_id: "post_id_0"
     uid: "uid_1"
     likes: "10"
   comment_1
     post_id: "post_id_0"
     uid: "uid_1"
     likes: "7"
   comment_2
     post_id: "post_id_1"
     uid: "uid_1"
     likes: "2"
设置:

class CommentClass {
    var commentKey = ""
    var comment = ""
    var likes = ""
}

var postsArray = [ [String: [String:AnyObject] ] ]()
var commentsArray = [CommentClass]()
加载所有立柱的代码:

    let postsRef = ref.child("posts")

    postsRef.observeSingleEvent(of: .value, with: { snapshot in

        for snap in snapshot.children {
            let postSnap = snap as! FIRDataSnapshot
            let postKey = postSnap.key //the key of each post
            let postDict = postSnap.value as! [String:AnyObject] //post child data

            let d = [postKey: postDict]
            self.postsArray.append(d)
        }
        //postsTableView.reloadData
        print(self.postsArray) //just to show they are loaded
    })
然后,当用户点击帖子时,加载并显示评论

    self.commentsArray = [] //start with a fresh array since we tapped a post
    //placeholder, this will be the post id of the tapped post
    let postKey = "post_id_0" 
    let commentsRef = ref.child("comments")
    let queryRef = commentsRef.queryOrdered(byChild: "post_id")
                              .queryEqual(toValue: postKey)

    //get all of the comments tied to this post
    queryRef.observeSingleEvent(of: .value, with: { snapshot in

        for snap in snapshot.children {
            let commentSnap = snap as! FIRDataSnapshot
            let commentKey = commentSnap.key //the key of each comment
            //the child data in each comment
            let commentDict = commentSnap.value as! [String:AnyObject] 
            let comment = commentDict["comment"] as! String
            let likes = commentDict["likes"] as! String
            let c = CommentClass()
            c.commentKey = commentKey
            c.comment = comment
            c.likes = likes

            self.commentsArray.append(c)
        }

        //commentsTableView.reload data

        //just some code to show the posts are loaded
        print("post:  \(postKey)")
        for aComment in self.commentsArray {
            let comment = aComment.comment
            print("  comment: \(comment)")
        }
    })
和结果输出

post:  post_id_0
  comment: I like post_id_0
  comment: post_id_0 is the best evah

上述代码经过测试,没有闪烁。显然,它需要根据您的用例进行调整,因为您需要加载一些图像等,但上述内容应该可以解决问题,并且更易于维护。

您的方法可能需要通过简化来调整。我想提供所有的螺母和螺栓,所以它有点长,本身可以简化

虽然非规范化是正常的,但这不是一项要求,在某些情况下可能会增加额外的复杂性。结构postCommentGroup中的“层”似乎不需要

看起来您有一个包含帖子的视图控制器,还有一个视图控制器,当用户点击第一个控制器上的帖子时,该控制器会显示注释

您实际上只需要一个posts节点和comments节点

posts
   post_id_0
     title: "my post title"
     caption: "some caption"
     uid: "uid_0"
   post_id_1
     title: "another post title
     caption: "another caption
     uid: "uid_0"
以及引用帖子的评论节点

comments
   comment_0
     post_id: "post_id_0"
     uid: "uid_1"
     likes: "10"
   comment_1
     post_id: "post_id_0"
     uid: "uid_1"
     likes: "7"
   comment_2
     post_id: "post_id_1"
     uid: "uid_1"
     likes: "2"
设置:

class CommentClass {
    var commentKey = ""
    var comment = ""
    var likes = ""
}

var postsArray = [ [String: [String:AnyObject] ] ]()
var commentsArray = [CommentClass]()
加载所有立柱的代码:

    let postsRef = ref.child("posts")

    postsRef.observeSingleEvent(of: .value, with: { snapshot in

        for snap in snapshot.children {
            let postSnap = snap as! FIRDataSnapshot
            let postKey = postSnap.key //the key of each post
            let postDict = postSnap.value as! [String:AnyObject] //post child data

            let d = [postKey: postDict]
            self.postsArray.append(d)
        }
        //postsTableView.reloadData
        print(self.postsArray) //just to show they are loaded
    })
然后,当用户点击帖子时,加载并显示评论

    self.commentsArray = [] //start with a fresh array since we tapped a post
    //placeholder, this will be the post id of the tapped post
    let postKey = "post_id_0" 
    let commentsRef = ref.child("comments")
    let queryRef = commentsRef.queryOrdered(byChild: "post_id")
                              .queryEqual(toValue: postKey)

    //get all of the comments tied to this post
    queryRef.observeSingleEvent(of: .value, with: { snapshot in

        for snap in snapshot.children {
            let commentSnap = snap as! FIRDataSnapshot
            let commentKey = commentSnap.key //the key of each comment
            //the child data in each comment
            let commentDict = commentSnap.value as! [String:AnyObject] 
            let comment = commentDict["comment"] as! String
            let likes = commentDict["likes"] as! String
            let c = CommentClass()
            c.commentKey = commentKey
            c.comment = comment
            c.likes = likes

            self.commentsArray.append(c)
        }

        //commentsTableView.reload data

        //just some code to show the posts are loaded
        print("post:  \(postKey)")
        for aComment in self.commentsArray {
            let comment = aComment.comment
            print("  comment: \(comment)")
        }
    })
和结果输出

post:  post_id_0
  comment: I like post_id_0
  comment: post_id_0 is the best evah

上述代码经过测试,没有闪烁。显然,它需要根据您的用例进行调整,因为您需要加载一些图像等,但上述内容应该可以解决问题,并且更易于维护。

我只在图片中体验到这种闪烁。每次在“收藏”视图中发生某些事情时,应用程序都会下载这些图片

我的解决方案是我在网上找到的。恩斯卡。 您可以缓存图像,如果