我的主要问题是如何消除闪烁,但我也只是想知道我是否正确且最有效地处理非规范化 Firebase 数据。我的方法接近正确吗?
因此,我正在努力尝试使用已非规范化的数据正确显示 firebase 数据库中的数据。我有帖子,然后是与每个帖子相关的评论。每当有人打开帖子的评论部分时,通过从视图控制器连接到新的视图控制器,它会获取帖子的唯一键 (postKey),然后扫描与 postCommentGroup 中包含的 postKey 关联的评论组。评论组是 postCommentGroup 中每个 postKey 的子级,只是 commentKey 作为键,“true”作为值,它指示哪些评论与哪些帖子关联。这些评论位于完全不同的分支中,因为我认为 Firebase 文档建议人们应该这样做。
我基本上有 3 层嵌套观察者。
为了清楚起见,我在表格视图中使用 dequeuereusablecells 回收单元格,并且我还有一个基本的延迟加载/图像缓存机制,这也可能会干扰事物,但我在其他不太复杂的表格视图上有相同的机制,所以我我不认为这是问题所在。
由于我缺乏知识,除了经历这个循环之外,我不知道如何显示数据。我认为这个循环可能会导致闪烁,但我不知道如何让它加载数据。我尝试过各种其他方法,例如使用查询,但我从未能够让它工作。
作为旁注,我试图加快如何查询数据的速度(我认为这可能对我有帮助),但是 Swift 的语法进行了更新,Firebase 也进行了更新,使得前面的示例成为可能有点难以理解。
另外,我就是找不到好的,recent在 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 {
}
}
UPDATE:
我弄清楚了如何使用之前的 stackoverflow 帖子中概述的查询和委托模式:
从从 firebase 检索数据的闭包中获取数据
但我不知道我是否正确使用了委托模式。
使用查询简化了代码,但还是闪烁。也许我没有正确使用委托模式?
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 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()
})
}