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 :
(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?
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 theUIImageView
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.