0

I have a uitableview where I use a custom cell. However, when I scroll the table view there is some serious lag. It happens when I set the UIImaveView's image property with an image. I am accessing an image from the directory. But since file IO is slow I am using the dispatch_async to load the image into a UIImage object on a separate thread.

However there is still some lag. When I scroll up and down the rows without any images, the scrolling is very smooth. However when the row actually has an image, there is lag. the momentum scrolling will halt, then the app becomes unresponsive, then when the image finally loads the momentum continues where it left off.

I am not sure what is causing the lag. At first I thought it had to do with the image being too large so i tried scaling it down. Still lags. Again, if I don't set the image in the custom cell there is no lag. But when I do set it there is lag. I am not sure how to fix this.

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    DHTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kReuseIdentifierGoalCell forIndexPath:indexPath];
    [self configureCell:cell forIndexPath:indexPath isForOffscreenUse:NO];

    return cell;
 }


- (void)configureCell:(DHTableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath isForOffscreenUse:(BOOL)offscreenUse {
    if (cell == nil) {
        return;
    }

    [cell setDelegate:self];

    PATH_TO_FILE = SQLITE_QUERY_TO_GET_PATH; //some pseudo codes

    __weak typeof(sSelf)wSelf = sSelf;
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         __strong typeof(wSelf)sSelf = wSelf;
         UIImage *unscaled_image = [UIImage imageWithContentsOfFile:PATH_TO_FILE];
         UIImage *image = [unscaled_image imageScaledToFitInSize:kCellUIImageSize];
         __weak typeof(sSelf)wSelf = sSelf;
         dispatch_async(dispatch_get_main_queue(), ^{
             __strong typeof(wSelf)sSelf = wSelf;
             DHTableViewCell *cell = (id)[sSelf.tableView cellForRowAtIndexPath:indexPath];
             if (cell) {
                 [cell.imageStored setImage:image]; //Commenting this out relieves all lag
             }
         });
     });
 }
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
DerrickHo328
  • 4,664
  • 7
  • 29
  • 50
  • Where do you call this code fragment from? And does each cell have a different image? – Paulw11 Jun 29 '14 at 04:19
  • It is called in tableview:cellforindexpath: – DerrickHo328 Jun 29 '14 at 05:13
  • Each cell has a different image. – DerrickHo328 Jun 29 '14 at 05:14
  • I am not aware of that method. Can you post the whole method. How is it related to `cellForRowAtIndexpath`? I notice that you call back into `cellForRowAtIndexPath` in this code, which seems odd. Normally you would load images in a background thread invoked in `cellForRowAtIndexPath` - and then you already have a reference to the cell – Paulw11 Jun 29 '14 at 05:18
  • ok, I updated the code to make it easier to understand. The reason I am usingcellForRowAtIndexPath to get a reference to the cell is because there is a chance that the cell might end up off screen by the time the image finally loads. The way tableviews work is by recycling the cells, thus if I only using the reference of the cell from the method, It might end up updating the wrong cell. (if I have misunderstood how this works please correct me) – DerrickHo328 Jun 29 '14 at 05:35
  • I made it based on [this](http://stackoverflow.com/a/16663759/3400034) – DerrickHo328 Jun 29 '14 at 05:37
  • OK, I didn't notice that it was the tableView method. Have you used the Instruments tool to profile your performance and see where time is being spent? – Paulw11 Jun 29 '14 at 05:45
  • I have used the Instruments tool. According to the Instruments tool... it is not accusing the image setting as hogging CPU time. Yet something about setting the image causes lag. I don't know why – DerrickHo328 Jun 29 '14 at 05:50
  • Have you tried putting an empty placeholder UIImage into the image view prior to loading? Have you tried a static image path, rather than using the query? – Paulw11 Jun 29 '14 at 06:20
  • by placeholder I assume you mean the default image I give it in Interface builder. I have tried adding and removing it and it does not seem to effect anything. – DerrickHo328 Jun 29 '14 at 06:28
  • I'm not sure how using a "static image path" would help. When I comment out the line "[cell.imageStored setImage:image];" the lag goes away. btw, imageStored is the UIImageView – DerrickHo328 Jun 29 '14 at 06:31
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/56469/discussion-between-paulw11-and-calimari328). – Paulw11 Jun 29 '14 at 07:02

1 Answers1

0

@Calimari328 I hate if to put this as an answer because it does not really answer your question but the truth is what you should really do is use a library to achieve this. for example SDWebImage

Example:

#import <SDWebImage/UIImageView+WebCache.h>

...

- (UITableViewCell *)tableView:(UITableView *)tableView
                            cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *MyIdentifier = @"MyIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:MyIdentifier] autorelease];
    }

    // Here we use the new provided setImageWithURL: method to load the web image
    [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
                   placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

    cell.textLabel.text = @"My Text";
    return cell;
}

You have to rethink this, cells get reused, that means each time you scroll your app will try to download images again.What about performance? memory ? cache ? processing?

As you think more about it is a lot more complex then a simple async task. Fortunately there are opensource projects to achieve this. No need to reinvent the wheel.

Please note I am not advertising any library if you want to write your own code you can do this as well. You can also search on the web for easy ones to implement.

meda
  • 45,103
  • 14
  • 92
  • 122
  • This is a fantastic Opensourced library, but my project is not loading it from the internet. it is loading it from disk. – DerrickHo328 Jun 29 '14 at 07:06
  • Again I can only suggest you to try it if you read the description it says `An asynchronous memory + disk image caching with automatic cache expiration handling` – meda Jun 29 '14 at 07:10