Reputation: 1271
I am using Kingfisher to download and cache remote images.
I would like to render those images in a UITableViewCell
Currently the images do not show until I scroll.
I suspect this is because the initial image size is nil, once I scroll the cell is redrawn and the image is rendered.
To negate this issue I have called tableView.reloadRows(at: [indexPath], with: .none)
in the completion handler of Kingfisher
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FeedTableViewCellId", for: indexPath) as! FeedGifCell
let url = URL(string: items[indexPath.item])!
let imageView = ImageResource(downloadURL: url, cacheKey: "\(url)-imageview")
let placeHolderImage = UIImage.from(hex: "ffffff").resize(width: 1, height: 190)
cell.gifImage.kf.setImage(with: imageView, placeholder: placeHolderImage) { _ in
tableView.reloadRows(at: [indexPath], with: .none)
}
return cell
}
I have applied a simple placeholder of a fixed height and width to give the cell some height before the image is applied.
I am not sure this is the best approach, I do not like calling tableView.reloadRows(at: [indexPath], with: .none)
this feels a little.....hacky.
Also, before the cell is redrawn I have the white space, my placeholder, then a jump as the correct image / size is applied.
Is it possible to simply prevent the cell from being visible at all until the image has been applied?
Upvotes: 1
Views: 1802
Reputation: 13283
No! You don't have to reload the tableView in any way after the image in a certain cell gets done downloading. Other than that, you're doing everything correctly. I use Kingfisher too.
But in the future, you could just make a function in your cell class, say setupCell(_ imageURL: URL?)
. Anyways, going on, in your cellForRow
method, just do it like this:
cell.gifImage.kf.setImage(with: imageView, placeholder: placeHolderImage, completionHandler: nil)
Now, in case that there's no image downloaded or you have no image URL string to be made to URL
object, you could catch it in Kingfisher's error block, then you will need to pass your error image
(a UIImage
) object to your imageView
so that there would be no duplicate image.
For example, I have the following in my cell's setupCell()
function:
if let url = vendor.image?.URLEscaped {
let resource = ImageResource(downloadURL: url, cacheKey: url.absoluteString)
self.imageView_Vendor.kf.setImage(with: resource, options: [.transition(.fade(0.2)), .cacheOriginalImage])
return
}
self.imageView_Vendor.image = nil
I hope this helps!
EDIT:
For the handling of image height, this could help: https://stackoverflow.com/a/52787062/3231194
Upvotes: 2