Swift 有序阵列闪烁效应?
当我从有序数组加载数据时,表视图会在加载时遍历每个单元格。似乎是先加载表视图,然后对数组进行排序,这会导致闪烁效果。这反过来也会弄乱每个细胞的图像 这是在快照获取数据后调用的Swift 有序阵列闪烁效应?,swift,uitableview,firebase,firebase-realtime-database,tableview,Swift,Uitableview,Firebase,Firebase Realtime Database,Tableview,当我从有序数组加载数据时,表视图会在加载时遍历每个单元格。似乎是先加载表视图,然后对数组进行排序,这会导致闪烁效果。这反过来也会弄乱每个细胞的图像 这是在快照获取数据后调用的 postReference.observeSingleEvent(of: .value, with: { (snapshot) in if let value = snapshot.value as? NSDictionary { let post
postReference.observeSingleEvent(of: .value, with: { (snapshot) in
if let value = snapshot.value as? NSDictionary {
let post = Post()
let post_content = value["post"] as? String ?? "Content not found"
post.revealDate = value["revealedDate"] as? Double ?? 0000000
self.postList.append(post)
}
self.postList.sort() { $0.revealDate! > $1.revealDate! }
self.tableView.reloadData()
}
这样就可以加载电池了
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if queryComplete == true{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! PostTableViewCell
//set cell content
let contentOfCellPost = postList[indexPath.row]
cell.label?.text = contentOfCellPost.post_words
return cell
似乎表视图正在加载每个单元格作为第一个单元格,然后对其进行排序
编辑
整个firebase初始数据负载观测:
func fetchFeed () {
let UID = Auth.auth().currentUser?.uid
feedReference = Database.database().reference().child("feeds").child(UID!)
feedReference.keepSynced(true)
self.postRefHandle = feedReference.observe(.childAdded) { (snapshot) in
let postID = snapshot.key
let postReference = Database.database().reference().child("posts").child(postID)
postReference.observeSingleEvent(of: .value, with: { (snapshot) in
if let value = snapshot.value as? NSDictionary {
let post = Post()
let post_content = value["post"] as? String ?? "Content not found"
post.Reveals = value["reveals"] as? Int ?? 10000000
post.revealsRequired = value["revealsRequired"] as? Int ?? 100000
post.post_words = post_content
post.postID = postID
post.Revealed = value["Revealed"] as? String ?? "Revealed or Not not found"
post.revealsRequired = value["revealsRequired"] as? Int ?? 1000000000
post.revealDate = value["revealedDate"] as? Double ?? 0000000
post.timeOfDeletion = value["timeOfDeletion"] as? Int ?? 100000000000
if snapshot.hasChild("information") {
if let infoName = snapshot.childSnapshot(forPath: "information").value as? NSDictionary {
post.name = infoName["posterName"] as? String ?? "Poster not found"
post.profileImageLink = infoName["profileImage"] as? String ?? "nil"
post.revealedBool = true
self.postList.append(post)
}
} else {
let date = Date()
let currentTime = date.timeIntervalSince1970 * 1000
let timeToDelete = Int(post.timeOfDeletion!) - Int(currentTime)
post.revealedBool = false
post.name = String(timeToDelete)
self.postList.append(post)
}
self.postList.sort() { $0.revealDate! > $1.revealDate! }
self.tableView.reloadData()
}
})
}
}
观察职位变动情况:
postReference.observe(.value, with: { snapshot in
if self.queryComplete == true {
let changedKey = snapshot.key
if let index = self.postList.index(where: {$0.postID == changedKey}) {
let indexPath = IndexPath(row: index, section: 0)
let changedPost = self.postList[index]
if let value = snapshot.value as? NSDictionary {
let newReveals = value["reveals"] as? Int
changedPost.Reveals = newReveals
//update the values
self.tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.none)
}
if let value = snapshot.value as? NSDictionary {
let newRevealStatus = value["Revealed"] as? String ?? "noRevealStatusChange"
changedPost.Revealed = newRevealStatus
if changedPost.Revealed == "true" {
changedPost.revealedBool = true
changedPost.revealDate = value["revealedDate"] as? Double ?? 00000
if let newName = snapshot.childSnapshot(forPath: "information").value as? NSDictionary {
changedPost.name = newName["posterName"] as? String ?? "Poster not found"
changedPost.profileImageLink = newName["profileImage"] as? String ?? "nil"
self.postList.sort() { $0.revealDate! > $1.revealDate! }
self.tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.none)
}
}
}
}
}
self.queryComplete = true
} )
JSON示例:
"feeds" : {
"3ASP4M5mkTPGPO1qQhfVKXsr6Qf2" : {
"-L65VFpW2cYIMxG2e9Ll" : "true",
"-L65VH5jkKPYAguzgqpn" : "true"
}
"posts" : {
"-L7CpeKT2lzsPALAfNti" : {
"Revealed" : "true",
"datePosted" : "2018-03-10 02:56:33 +0000",
"information" : {
"posterID" : "BmVot3XHEpYwMNtiucWSb8XPPM42",
"posterName" : "tester",
"profileImage" : "nil"
},
编辑:使用较少的观察者修改代码:
func fetchFeed () {
let UID = Auth.auth().currentUser?.uid
feedReference = Database.database().reference().child("feeds").child(UID!)
feedReference.keepSynced(true)
self.postRefHandle = feedReference.observe(.childAdded) { (snapshot) in
let postID = snapshot.key
let postReference = Database.database().reference().child("posts").child(postID)
postReference.observe(.value, with: { (snapshot) in
let postKey = snapshot.key
if let value = snapshot.value as? NSDictionary {
if let index = self.postList.index(where: {$0.postID == postKey}) {
let indexPath = IndexPath(row: index, section: 0)
let changedPost = self.postList[index]
let newReveals = value["reveals"] as? Int
changedPost.Reveals = newReveals
//update the values
self.tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.none)
let newRevealStatus = value["Revealed"] as? String ?? "noRevealStatusChange"
changedPost.Revealed = newRevealStatus
if changedPost.Revealed == "true" {
changedPost.revealedBool = true
changedPost.revealDate = value["revealedDate"] as? Double ?? 00000
if let newName = snapshot.childSnapshot(forPath: "information").value as? NSDictionary {
changedPost.name = newName["posterName"] as? String ?? "Poster not found"
changedPost.profileImageLink = newName["profileImage"] as? String ?? "nil"
self.postList.sort() { $0.revealDate! > $1.revealDate! }
self.roundButton.isHidden = false
}
}
self.tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.none)
}
//appending to row for first time (initial load)
else {
if let value = snapshot.value as? NSDictionary {
let post = Post()
let post_content = value["post"] as? String ?? "Content not found"
post.Reveals = value["reveals"] as? Int ?? 10000000
post.revealsRequired = value["revealsRequired"] as? Int ?? 100000
post.post_words = post_content
post.postID = postID
post.Revealed = value["Revealed"] as? String ?? "Revealed or Not not found"
post.revealsRequired = value["revealsRequired"] as? Int ?? 1000000000
post.revealDate = value["revealedDate"] as? Double ?? 0000000
post.timeOfDeletion = value["timeOfDeletion"] as? Int ?? 100000000000
if snapshot.hasChild("information"){
if let infoName = snapshot.childSnapshot(forPath: "information").value as? NSDictionary {
post.name = infoName["posterName"] as? String ?? "Poster not found"
post.profileImageLink = infoName["profileImage"] as? String ?? "nil"
post.revealedBool = true
self.postList.append(post)
}
}
else {
let date = Date()
let currentTime = date.timeIntervalSince1970 * 1000
let timeToDelete = Int(post.timeOfDeletion!) - Int(currentTime)
post.revealedBool = false
post.name = String(timeToDelete)
self.postList.append(post)
}
// self.deletePosts()
self.postList.sort() { $0.revealDate! > $1.revealDate! }
self.tableView.reloadData()
}
}
}
else {
Database.database().reference().child("feeds").child(self.userIDCurrent!).child(postID).removeValue()
}
})
}
self.queryComplete = true
}
我将对此进行一次尝试,并通过提出另一个方向来解决这个问题。如果这是远离基地,让我知道,我可以更新或删除 问题中有很多代码需要排序,但表面上看,似乎添加了大量的观察者,重新加载数据并频繁刷新tableView 据我所见,feeds节点用于收集数据组;用户感兴趣的一组帖子、一组日期、一组朋友等。每个帖子都是提要,每个连接到该提要的节点都添加了一个观察者 我的建议是从更高的层次着手,而不是用一个独立的观察者来处理每个子节点,比如说‘嘿,Firebase,在这个父节点中,如果子节点满足某个标准,请让用户知道它’ 因此,让我们利用Firebase深度查询以更少的观察者完成同样的任务 以职位结构为例
posts
post_0
name: "Jim"
post: "We have them just where they want us"
watched_by:
uid_0: true
uid_1: true
post_1
name: "Spock"
post: "Nothing unreal exists"
watched_by:
uid_1: true
post_2
name: "Bones"
post: "I'm a doctor, not an escalator"
watched_by
uid_0: true
并假设uid为0的用户进行身份验证。此前,他们决定观看吉姆和博恩斯的帖子。正如您从结构中看到的,我们在每篇文章中都有一个watched_by节点,并向该节点添加了uid_0:true
因此,现在让uid_0观察posts节点,查看他们感兴趣的posts的更改:
let postsRef = self.ref.child("posts")
let watchedByQuery = postsRef.queryOrdered(byChild: "/watched_by/uid_0").queryEqual(toValue: true)
watchedByQuery.observe(.childChanged, with: { snapshot in
let dict = snapshot.value as! [String: Any]
let post = dict["post"] as! String
print(snapshot.key, post)
})
因此,如果Bones登录并将其帖子从“我是医生,不是自动扶梯”更改为“我是医生,不是砖匠”,则该节点将被发送到uid_0,以便更新ui
post_2
name: "Bones"
post: "I'm a doctor, not a bricklayer"
watched_by
uid_0: true
在此基础上进一步扩展,我们显然将使用相同的技术添加.childAdded和.childremove,并且.childAdded将在每个用户进行身份验证时,首先为他们填充tableView数据源
假设Bones然后完全删除他的帖子(节点)。监视者列表中的任何用户都将收到该事件的通知(甚至数百万用户)。当这种情况发生时,在代码中,从快照中读取post_2的键,在数据源数组中找到它,删除它并更新tableView
再一次-我的答案完全是黑暗中的。@代码不同,在添加单元格之前,我如何重新加载特定行?如何获取索引路径?对于按.value观察节点,该代码看起来有点奇怪。你能在你的问题中加入一段Firebase结构作为文本,这样我们可以看一下吗?@Jay,我更新了代码。json结构使用一个扇出系统,使得post ID位于每个提要中。在观察数据时,我首先收集提要中的每个帖子,然后为初始加载创建一个单独的引用。然后,我为每一篇只是观察变化的帖子做了一个参考,但为了简洁起见,我没有包括代码。事件的顺序有点不清楚,但有一件事突然出现在我面前(如果我有误解,请纠正我)您正在使用postReference.observeSingleEvent填充数据源数组,但在某个时候,这种情况会发生在postReference.observeSingleEvent(.值,该值基本上会重新加载相同的数据,但会留下一个观察者。第一个观察者会更新整个tableView,第二个观察者会再次更新这些相同的行。似乎所有这些都可以组合到一个观察者调用中,以填充posts数组,并让观察者观察这些POST的更改。我面临一点困难ilemma。您提供的结构更有效,减少了观察者,并防止了闪烁。然而,帖子将所有被关注的数据发送给访问它的每个用户,整个想法应该是关于匿名发布。因此,当用户访问帖子时,尽管UI没有显示它,但所有数据(包括用户的朋友是谁)将被发送到每个提要…这是一个严重的问题吗?有没有关于如何避免此问题的建议?@RaimKhalil UID非常通用,不包含任何直接的用户信息。因此,即使应用程序接收到一堆UID,也没有回溯来查看谁是谁。更重要的是,用户必须调试您的源代码,然后重新登录首先查看该快照以查看uid是什么。如果它让您感觉更舒服,请不要使用uid,使用其他随机生成的字符串或UUID,并将其存储在每个用户/用户节点中,如/users/uid\x/my\u random\u code:xyzy,然后使用该代码代替uid进行观察。@RaimKhalil这是来自Firebaser answ的链接呃,这说明UID的安全性非常有意义!感谢过去几天的帮助,我认为UID的安全性很好。@RaimKhalil查询是在服务器端完成的,发送到应用程序的唯一数据是与查询匹配的数据。换句话说,如果您为/watched_向节点添加childAdded查询/uid\u 0添加到应用程序的节点只有那些与之匹配的节点。其他节点将被忽略。