Menu & Search

Dynamic UITableView Row Height for Downloaded Images

June 7, 2015

This is an it’sbstacle I’ve encountered a few times in the past.

You’re fetching images from an API or another resource and you don’t know the dimensions beforehand, but you want each image to be displayed as big as possible.

To be completely honest, there is no perfect solution for this. If you really don’t have a way of getting the dimensions before downloading the image, you’ll have to do a few extra steps to make the UI really slick!

Let’s look at the fastest way to get this working and your table view rows resized properly.

Downloading images

We’ll be using AFNetworking (more specifically – their UIImageView+AFNetworking.h category) to dynamically fetch images.

The catch

The main catch here is that we’ll store image dimensions in an array so we’ll know the height of each row when tableView:heightForRowAtIndexPath: is called.

The simplest way of doing this is to use the  setImageWithURLRequest:placeholder:success:failure:  method provided by AFNetworking. Here, we’ll download the image, store its height to an array we’ll name imageHeights and update our table view to reflect the height changes.

But first, let’s fill  imageHeights with default values (the default rowHeight property of our table view.

Then, let’s move on to tableView:cellForRowAtIndexPath: where we’re downloading the images and storing their height in our imageHeights  array (this is a long one, but don’t freak out).

Ok, so now we have all the images’ heights stored in an array. How do we use them?

Simple! We can now return proper values in the tableView:heightForRowAtIndexPath: method like this:

Reloading table view cells properly

Try experimenting with a few different approaches. I found that calling only beginUpdates  and endUpdates  produces the best animation/transition when cell height is changed. You could also put in the reloadRowsAtIndexPaths:withRowAnimation:  call between those two but it does an extra refresh and the UI looks crappy.

Is this it?

Like I said, this is not the best solution, but it’s the fastest and probably the simplest. If you’re working with a backend developer, try to convince him to put image dimensions in the API. That way, you won’t have to download each image before having the right height for the tableView:heightForRowAtIndexPath: method. If you’re dealing with a designer that wants dynamic row heights, try to convince him or her that, considering all the facts, it’s not a great idea since the UX won’t be as good as it can be with fixed or pre-determined heights.

TL;DR

The simplest and fastest way of accomplishing this is to download each image and store its height into an array that we then use to display different heights for different rows using UITableViewDelegate ‘s  tableView:heightForRowAtIndexPath: callback.

Source

As always, take a look at the full project on GitHub (branch: static-images) or download the .zip archive directly.

STOP LOSING TIME WITH AUTO LAYOUT!

Take part in the 5-day course with actionable tasks that will let you become a master at recognizing and solving the most common mistakes iOS developers do with Auto Layout.

Let Auto Layout become a tool you swing with your utmost confidence!

I won't send you spam, I promise. Unsubscribe at any time. Powered by ConvertKit
Hey there! You're already subscribed to my newsletter and you've hopefully gotten some useful tips and tricks when working with iOS. If you're also working with Auto Layout, make sure to check out my book called Auto Layout Fundamentals and get a 20% off for being my subscriber! https://gum.co/autolayoutfundamentals/youareawesome
Jure Zove

A lot of things but mostly a programmer who really likes fast cars. Check me out on Twitter, if you fancy.

Related article

Introducing The “How do I Auto Layout” Cheatsheet

STOP LOSING TIME WITH AUTO LAYOUT! Take part in the…

Fastest way to use Auto Layout in code

Raise your ✋ if you hate adding views and setting…

Swift Optionals Demystified

STOP LOSING TIME WITH AUTO LAYOUT! Take part in the…

Type your search keyword, and press enter to search