gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-11-01 06:17:21 25 4
gpt4 key购买 nike

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

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

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

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

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

附带说明一下,我已经尝试快速了解如何查询数据(我认为这可能对我有帮助),但是 Swift 的语法有了更新,Firebase 也有了更新,使得前面的例子有点难以理解。

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

这是 Firebase 数据结构:

   
"comments" : {
"-KaEl8IRyIxRbYlGqyXC" : {
"description" : "1",
"likes" : 1,
"postID" : "-KaEfosaXYQzvPX5WggB",
"profileImageUrl" : "https://firebasestorage.googleapis.com",
"timePosted" : 1484175742269,
"userID" : "9yhij9cBhJTmRTexsRfKRrnmDRQ2",
"username" : "HouseOfPaine"
}
},

"postCommentGroup" : {
"-KaEfosaXYQzvPX5WggB" : {
"-KaEl8IRyIxRbYlGqyXC" : true,
"-KaEl9HiPCmInE0aJH_f" : true,
"-KaF817rRpAd2zSCeQ-M" : true
},
"-KaF9ZxAekTEBtFgdB_5" : {
"-KaFEcXsSJyJwvlW1w2u" : true

},
"-KaJyENJFkYxCffctymL" : {
"-KaQYa0d08D7ZBirz5B4" : true
}
},
"posts" : {
"-KaEfosaXYQzvPX5WggB" : {
"caption" : "Test",
"comments" : 11,
"imageUrl" : "https://firebasestorage.googleapis.com/",
"likes" : 0,
"profileImageUrl" : "https://firebasestorage.googleapis.com/",
"timePosted" : 1484174347995,
"title" : "test",
"user" : "17lIDKNx6LgzQmaeQ2ING582zi43",
"username" : "Freedom"
}
},

这是我的代码:

func commentGroupObserver() {

DataService.ds.REF_POST_COMMENT_GROUP.observeSingleEvent(of: .value, with: { (snapshot) in

if snapshot.value != nil {

if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] , snapshots.count > 0 {

self.comments = []

for snap in snapshots {

if let tempVarPostKeyForCommentGroup = snap.key as String? {

if tempVarPostKeyForCommentGroup == self.post.postKey {

self.postKeyForCommentGroup = tempVarPostKeyForCommentGroup

self.commentObservers()
} else {

}
} else {

}
}

}

} else {
print("error")
}

})


}


func commentObservers() {

if postKeyForCommentGroup != nil {

constantHandle = DataService.ds.REF_POST_COMMENT_GROUP.child(postKeyForCommentGroup).observe(.value, with: { (snapshot) in

if snapshot.value != nil {

if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot], snapshots.count > 0

{

self.comments = []

for snap in snapshots {

if let theCommentIDForEachComment = snap.key as String? {
DataService.ds.REF_COMMENTS.child(theCommentIDForEachComment).queryOrdered(byChild: "timePosted").observeSingleEvent(of: .value, with: { (snapshots) in

if let commentDict = snapshots.value as? Dictionary<String, AnyObject> {

let key = snapshots.key
let comment = Comment(commentKey: key, dictionary: commentDict)
self.comments.insert(comment, at: 0)
}
self.tableView.reloadData()
})
}
}
}

} else {

}
})

} else {

}

}

更新:

我在之前的 stackoverflow 帖子中找到了如何使用查询和委托(delegate)模式的方法:

getting data out of a closure that retrieves data from firebase

但我不知道我是否正确使用了委托(delegate)模式。

代码已经通过使用query进行了简化,但是还是闪烁不定。也许我没有正确使用委托(delegate)模式?

    func commentGroupObserver() {
DataService.ds.REF_POST_COMMENT_GROUP.queryOrderedByKey().queryStarting(atValue: post.postKey).queryEnding(atValue: post.postKey).observeSingleEvent(of: .value, with: { (snapshot) in
self.postKeyForCommentGroup = self.post.postKey
self.commentObservers()
})

}

func commentObservers() {
if postKeyForCommentGroup != nil {
constantHandle = DataService.ds.REF_POST_COMMENT_GROUP.child(postKeyForCommentGroup).observe(.value, with: { (snapshot) in
if snapshot.value != nil {
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot]
{
self.comments = []
for snap in snapshots {
if let theCommentIDForEachComment = snap.key as String? {
DataService.ds.REF_COMMENTS.child(theCommentIDForEachComment).queryOrdered(byChild: "timePosted").observe(.value, with: { (snapshots) in

if let commentDict = snapshots.value as? Dictionary<String, AnyObject> {

let key = snapshots.key
let comment = Comment(commentKey: key, dictionary: commentDict)
self.comments.insert(comment, at: 0)

}

self.didFetchData(comments: self.comments)

})



}

}

}

} else {

}
})

} else {

}

}

func didFetchData(comments data:[Comment]){
self.tableView.reloadData()
}

和协议(protocol)

 protocol MyDelegate{
func didFetchData(comments:[Comment]) }

我这边解决问题的代码:

在Jay的建议下,我去掉了不必要的postCommentGroup,只在评论下查询了评论所属帖子的UID:

    func commentObservers() {

let queryRef = DataService.ds.REF_COMMENTS.queryOrdered(byChild: "postID").queryEqual(toValue: self.post.postKey)

queryRef.observe(.value, with: { snapshot in

if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {

for snap in snapshots {

if let commentDict = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let comment = Comment(commentKey: key, dictionary: commentDict)
self.comments.insert(comment, at: 0)
}
}
}

self.tableView.reloadData()
})
}

最佳答案

您的方法可能需要通过简化进行调整。我想提供所有的具体细节,所以它有点冗长,本身可以简化。

虽然反规范化是正常的,但这不是必需的,并且在某些情况下会增加额外的复杂性。您的结构 postCommentGroup 中的“层”似乎是不需要的。

看起来您有一个包含帖子的 View Controller ,以及一个在用户点击第一个 Controller 上的帖子时显示评论的第二个 View Controller 。

你真的只需要一个帖子节点和一个评论节点

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

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

关于ios - 新的 Firebase 数据导致 TableView 单元格闪烁 (Firebase/iOS/Swift),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41640063/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com