iosswiftuitableviewpfquery

Pictures shifting randomly in UITableView after reloading data


Pictures in my tableView are shifting around and are not being displayed on the correct posts after reloading the tableView. I cannot figure how to fix this.

https://i.sstatic.net/4hUbYm.jpg

The image above would be the normal image, however sometimes I get:

https://i.sstatic.net/PVEVrm.png

I've also did the prepareForReuse() function in the custom cell class but still doesn't work.

Here is the source code:

class UserPostsController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    @IBOutlet weak var userPostsTable: UITableView!

    var images : [UIImage] = []
    var descriptions : [String] = []
    var likes : [String] = []
    var dislikes : [String] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.font: UIFont(name: "Pacifico", size: 30)!]

        userPostsTable.dataSource = self
        userPostsTable.delegate = self

        let postQuery = PFQuery(className: "Post")
        postQuery.whereKey("userid", equalTo: PFUser.current()?.objectId as Any)
        postQuery.findObjectsInBackground { (objects, error) in
            if let posts = objects {
                for post in posts {
                    if let descripiton = post["description"] {
                        self.descriptions.append(descripiton as! String)
                    }
                    if let l = post["likes"] {
                        self.likes.append(l as! String)
                    }
                    if let d = post["dislikes"] {
                        self.dislikes.append(d as! String)
                    }
                    if let imageFile = post["imageFile"] as? PFFile {
                        imageFile.getDataInBackground(block: { (data, error) in
                            if let imageData = data {
                                if let image = UIImage(data: imageData) {
                                    self.images.append(image)
                                }
                            }
                            self.userPostsTable.reloadData()    
                        })
                    }
                }
            }
        }
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return images.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let cell = userPostsTable.dequeueReusableCell(withIdentifier: "userPostCell", for: indexPath) as? UserPostsTableViewCell {
            cell.descriptionLabel.text = descriptions[indexPath.row]
            cell.numerLikes.text = "\(likes[indexPath.row]) likes"
            cell.numberDislikes.text = "\(dislikes[indexPath.row]) dislikes"
            cell.postImage.image = images[indexPath.row]

            cell.selectionStyle = .none

            return cell
        }
        return UITableViewCell()
    }

Solution

  • I think you problem is here:

    if let imageFile = post["imageFile"] as? PFFile {
                        imageFile.getDataInBackground(block: { (data, error) in
                            if let imageData = data {
                                if let image = UIImage(data: imageData) {
                                    self.images.append(image)
    
                                }
    
                            }
                            self.userPostsTable.reloadData()    
                        })
    

    You are starting background tasks to get images data. Any of these tasks could finish first, please debug your array and you might find that the images are not in the desired order.

    Here is an apple sample project that might help you properly load those images in background.

    https://developer.apple.com/library/archive/samplecode/LazyTableImages/Introduction/Intro.html