FS.O6 FS.O6 - 1 month ago 13
Swift Question

Load UITableView images on background thread

I have an app that present images that sent from the server (similar to Instagram) using a tableView.

from the server I got:


  • Full size image URL

  • Description (String)

  • Image width

  • Image height



and I have a custom cell that present that as I want.

Like Instagram, the height of the image isn't fixed, so the cell's height changes dynamically to the image's height.

The image that I get from the server is really big, so I crop every image to be
Width - Screen's width, Height - Based of the width (keeps the ratio)
, like that:

func imageWithImage (sourceImage:UIImage, scaledToWidth: CGFloat) -> UIImage {
let oldWidth = sourceImage.size.width
let scaleFactor = scaledToWidth / oldWidth

let newHeight = sourceImage.size.height * scaleFactor
let newWidth = oldWidth * scaleFactor

UIGraphicsBeginImageContext(CGSize(width:newWidth, height:newHeight))
sourceImage.draw(in: CGRect(x:0, y:0, width:newWidth, height:newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}


my problem is that the tableView is VERY slow. So I thought of loading and cropping the images in a background thread and while its loading to present a default image.

I've tried that (using SDKs like
Alamofire
,
Kingfisher
etc...) but then the size of the cells (
UITableViewAutomaticDimension
) were a mess (because of the dynamic height), the images changed to wrong images while scrolling and sometimes even crashed while scrolling.

So that's why I'm asking here, how can I load the cells in a background thread and to keep its dynamic size, its correct photos and to avoid crashing?

Thank you very much in advanced for you answers!

Note: I know both Swift and Objective-C, select your favorite :)

Answer

I recommend using Alamofire for this. Check out this answer, providing both a solution using Alamofire and a custom one.

Edited post comments:

For calculating the cell height based on the image, you will need to download and cache those images prior to reloading your tableView, as heightForRowAtIndexPath will be called before cellForRowAtIndexPath, so you need to know the image height before actually setting it as that cell's property. This answer is what you need for that.

Comments