As my title states, the pictures in my tableView shift around and are not being displayed on the correct posts when scrolling through the table view. After I stop scrolling they seem to be back into place.
I've been trying to make a sense out of the following articles:
new Firebase retrieve data and put on the tableview swift
retrieve image from Firebase storage to show on tableview swift
swift Firebase sort posts in tableview by date
But I cannot figure out how to make the pictures to display better. Here's what I have:
import UIKit
import FirebaseAuth
import FirebaseDatabase
import FirebaseStorage
class MainFeedTableViewController: UITableViewController {
var posts = [Post]()
let alert = AlertsViewController()
var databaseRef: FIRDatabaseReference! {
return FIRDatabase.database().reference()
}
var storageRef: FIRStorage! {
return FIRStorage.storage()
}
override func viewDidLoad() {
super.viewDidLoad()
fetchPosts()
}
// populates the tableView with posts content in real time
private func fetchPosts(){
let postRefs = databaseRef.child("posts")
postRefs.observe(.value) { (snapshot: FIRDataSnapshot) in
var newPost = [Post]()
for post in snapshot.children{
let postObject = Post(snapshot: post as! FIRDataSnapshot)
newPost.insert(postObject, at: 0)
}
self.posts = newPost
self.tableView.reloadData()
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let postsAtIndexPath = posts[indexPath.row]
if postsAtIndexPath.postWithImage == true {
let cell = tableView.dequeueReusableCell(withIdentifier: "postWithImage", for: indexPath) as! PostWithImageTableViewCell
let postUser = postsAtIndexPath.uid
let userRef = databaseRef.child("users/\(postUser!)")
userRef.observe(.value, with: { (snapshot) in
let user = User(snapshot: snapshot)
DispatchQueue.main.async(execute: {
cell.userRealNameLabel.text = user.name
cell.usernameLabel.text = "@" + user.username
cell.postTextView.text = postsAtIndexPath.postText
cell.timeStampLabel.text = postsAtIndexPath.date
})
self.storageRef.reference(forURL: user.photoURL).data(withMaxSize: 1 * 1024 * 1024, completion: { (data, error) in
if error == nil{
DispatchQueue.main.async(execute: {
if let data = data{
cell.userProfilePicture.image = UIImage(data: data)
}
})
}
else{
print(error!.localizedDescription)
}
})
self.storageRef.reference(forURL: postsAtIndexPath.postPictureURL).data(withMaxSize: 1 * 1024 * 1024, completion: { (data, error) in
if error == nil{
DispatchQueue.main.async(execute: {
if let data = data{
cell.postImage.image = UIImage(data: data)
}
})
}
else{
self.alert.displayAlert(alertTitle: "Error", alertMessage: error!.localizedDescription, fromController: self)
}
})
}) { (error) in
self.alert.displayAlert(alertTitle: "Error", alertMessage: error.localizedDescription, fromController: self)
}
return cell
}
else{
let cell = tableView.dequeueReusableCell(withIdentifier: "postWithText", for: indexPath) as! PostTableViewCell
let postUser = postsAtIndexPath.uid
let userRef = databaseRef.child("users/\(postUser!)")
userRef.observe(.value, with: { (snapshot) in
let user = User(snapshot: snapshot)
DispatchQueue.main.async(execute: {
cell.userRealNameLabel.text = user.name
cell.usernameLabel.text = "@" + user.username
cell.postTextView.text = postsAtIndexPath.postText
cell.timestampLabel.text = postsAtIndexPath.date
})
self.storageRef.reference(forURL: user.photoURL).data(withMaxSize: 1 * 1024 * 1024, completion: { (data, error) in
if error == nil{
DispatchQueue.main.async(execute: {
if let data = data{
cell.userProfilePicture.image = UIImage(data: data)
}
})
}
else{
print(error!.localizedDescription)
}
})
}) { (error) in
self.alert.displayAlert(alertTitle: "Error", alertMessage: error.localizedDescription, fromController: self)
}
return cell
}
}
}
The reason I'm having a hard time, it's because I want the user's username, name, and profile picture to change everywhere and in real time when they edit their info. That's why I'm retrieving the user info based on the post's user uid.
What's a better way to implement this?