Async image set to cell with dynamic height bug

雨燕双飞 提交于 2020-01-06 14:01:17

问题


I'm experiencing bugs with my application when I'm trying to download and set an image async to a cell with dynamic height.

Video of the bug: https://youtu.be/nyfjCmc0_Yk


I'm clueless: can't understand why it happens. I'm saving the cell heights for preventing jumping issues and stuff, I do even update the height of the cell after setting the image.


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {



            var post : Post
            var cell : PostCell
            post = Posts.shared.post(indexPath: indexPath)

            // I REMOVED SOME NOT IMPORTANT PARTS OF THE CODE 
            // (like setting the text, etc)

            if post.images.count > 0 {
                // Images is attached to the post

                cell.postImageView.sd_setImage(with: URL(string: appSettings.url + "/resources/img/posts/" + post.images[0]), placeholderImage: nil, options: [.avoidAutoSetImage]) { (image, error, type, url) in
                    if let error = error {
                        // placeholder
                        return
                    }

                    DispatchQueue.main.async {
                        let cgRect = image!.contentClippingRect(maxWidth: 300, maxHeight: 400)
                        cell.postImageView.isHidden = false

                        cell.postImageWidthConstraint.constant = cgRect.width
                        cell.postImageViewHeightConstraint.constant = cgRect.height

                        cell.postImageView.image = image

                        cell.layoutIfNeeded()
                        self.cellHeights[indexPath] = cell.frame.size.height

                    }
                }


            } else {
                // No image is attached to the post
                cell.postImageViewHeightConstraint.constant = 0
                cell.postImageWidthConstraint.constant = 0
                cell.postImageView.isHidden = true
            }
            return cell


    }
    var cellHeights: [IndexPath : CGFloat] = [:]
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        cellHeights[indexPath] = cell.frame.size.height

        cell.layoutIfNeeded()

    }
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }
    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        if cellHeights[indexPath] != nil {
            return CGFloat(Float(cellHeights[indexPath] ?? 0.0))
        }
        else {
            return UITableViewAutomaticDimension
        }
    }

I've tried calling tableView.beginUpdates() tableView.endUpdates(), it fixes the problem at the beginning, but when scrolling it creates a weird bug :

https://youtu.be/932Kp0p0gfs

(random appearing small part of the image in the tableview)

And when scrolling up, it jumps to the beginning of the post.. maybe due to the incorrect height value?

What do I do wrong?


回答1:


You'll surely get such kind of bug if you are to compute the height and the width of the UIImage data and assign those values as the constraint constants of the UIImageView especially in a cell.

Solution for that? Make your datasource/server have a computed width and height and avoid computing it yourself. Meaning in your each Post object, there should be a ready width and height values. That's faster and that solved my issue the same as yours (see this cute personal quick project of mine: https://itunes.apple.com/us/app/catlitter-daily-dose-of-cats/id1366205944?ls=1&mt=8)

Also, I've learned that from some public APIs provided by some established companies like Facebook (each images have its computed sizes ready).

I hope this helps.



来源:https://stackoverflow.com/questions/52786947/async-image-set-to-cell-with-dynamic-height-bug

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!