When I load my data from an ordered array, the table view goes through every cell when loading. It seems as if the table view loads first and then the array is ordered, which leads to the flickering effect. This, in turn, also messes up the images that each cell has.
This is called after the snapshot gets the data
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()
}
and this loads the cell
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
It seems as if the table view is loading each cell as the first cell then ordering it afterwards.
EDIT
Entire firebase initial data load observation:
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()
}
})
}
}
Observing for changes in the post :
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 sample :
"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"
},
EDIT : Modified Code with less observers :
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
}