Question

I have a custom UITableViewCell. Each cell has an unique image.

I have an image loader class. I passed a dictionary to ImageLoader's method. A dictionary composed by image url and some other information. This code works well when we scroll down UITableView slowly. But if we scroll down rapidly it will have some lags. I need to optimize my algorithm. Any ideas.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
  [ImageLoader addImageToQueue:dictionary];
}
Was it helpful?

Solution

I believe that this tutorial would be useful in answering your question. It covers the reasons why you aren't able to scroll smoothly and how to fix it.

OTHER TIPS

  • Disable the image loading and test the table behavior - the problem might be a slow cell initialization, if the custom cell drawRect is overridden, pay much attention to this method as the documentation says it's navy usage slows the animations dramatically, find the way to optimize the drawing.
  • If the table scrolls smoothly with the image-loading disabled, consider to limit the number of the concurrent load operations (with the pending operations to be loaded later) and use caching whenever available.

Use UITableView dequeueReusableCellWithIdentifier:

This basically means that you don't have to recreate the table cell from scratch every time. If you give a cell a reuse identifier, it will keep ahold of that cell in memory and let you dequeue it when you ask for a cell matching that identifier.

Since every cell has a unique image, you'd probably be best off setting each cell's unique identifier as something from the image - perhaps the image's URL or filename. This will eat up more memory than disposing of and recreating the cells, but it reduces scroll lag, and if your images are small then the memory footprint isn't that large.

You'd probably end up with something like:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    NSString *imageURL = urlOfImageForThisCell;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:imageURL];
    if(!cell)
    {
        cell = [self makeNewCell];
        //if your reuseIdentifier is unique to each image, you only ever need to set it's image here
        cell.image = imageForThisCell;

        cell.reuseIdentifier = imageURL;
    }

    //additional cell setup here

    return cell;
}

You'll also want to look in subclassing UITableViewCell and overriding prepareForReuse.

I would check out Ray Wenderlich's tutorial on Multithreading and GCD here.

It's hard without seeing your cellForRowAtIndexPath: or ImageLoader code but I have a suspicion that your ImageLoader is slowing things down to the point where it has to wait for it to complete before it provides the cell. Even if it's just reading the image from the disk, it should be done on the background thread, asynchronously so that the main thread can focus on scrolling smoothly.

Good luck!

I know this is old, but I recommend this post: http://www.nsprogrammer.com/2013/10/easy-uitableview-buffering.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top