4

This has been driving me crazy for the better part of the day.

I've got a UITableView with UIImageViews. These imageviews load a locally saved PNG-file in the cellForRow-function of the tableview, and this works fine except the tableview will stop scrolling for a fraction of a second when a cell with an image in it scrolls into sight so to speak. I've trawled StackOverflow and google for an answer but I've come up short - so any help will be greatly appreciated.

Here is my code for the CellForRow-function:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {


    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];



    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MyIdentifier"] autorelease];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }

    if([currSection isEqualToString:@"composer"]){

        MySlide *s = [slidesArray objectAtIndex:indexPath.row];

        cell.textLabel.hidden = YES;
        UIImageView *whiteView = [[UIImageView alloc] initWithFrame:CGRectMake((projectsTable.frame.size.width/2)-150, 4, 204.8, 153.6)];

        if([s.slideImage isEqualToString:@""] || s.slideImage == nil){
            //no custom image in this cell - go with default background image

            whiteView.image = [UIImage imageNamed:@"cellback2.png"];
            whiteView.backgroundColor = [UIColor whiteColor];
        }else{
            cell.layer.shouldRasterize = YES;
            cell.layer.rasterizationScale = [UIScreen mainScreen].scale;

            NSData *data = [[NSData alloc] initWithContentsOfFile:s.slideImage];

            UIImage *im = [[UIImage alloc] initWithData:data];


            whiteView.image = im;

            whiteView.image = [self imageWithImage:whiteView.image CovertToSize:CGSizeMake(204.8,153.6)];
            whiteView.backgroundColor = [UIColor whiteColor];

        }


        [cell.contentView addSubview:whiteView];

        [whiteView release];



        cell.accessoryType = UITableViewCellAccessoryNone;

    }


  return cell;  
}
Stephen Darlington
  • 51,577
  • 12
  • 107
  • 152
PinkFloydRocks
  • 808
  • 3
  • 14
  • 29
  • 2
    this is happening cause each time its creating a new cell, alloc a imageview, formating and adding.. – vishy Feb 06 '12 at 11:45
  • I forgot to mention that I've tried to set up whiteBack inside the if(cell == nil) statement, but Ive not been able to update the imageview's image when adding a new image path to the slide object. Could you please give me a simple example of how you would solve this? – PinkFloydRocks Feb 06 '12 at 11:51
  • check my code in answer, i have updated.. – vishy Feb 06 '12 at 11:55

3 Answers3

6

There are a couple of changes to be made, first off the UIImageViews should be added when the cell is generated, rather than every time tableView:cellForRowAtIndexPath: is hit (as @Vishy suggests). Secondly you should cache the images you are loading from the documents directory ([UIImage imageNamed:] does this automatically for bundle resources).

@interface MyViewController () {

    NSMutableDictionary *_imageCache;
}

@end


@implementation MyViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // other viewDidLoad stuff...

    _imageCache = [[NSMutableDictionary alloc] init];
}

- (void)viewDidUnload {
    [super viewDidUnload];

    // other viewDidUnload stuff...

    [_imageCache release];
    _imageCache = nil;
}

- (void)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];

    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MyIdentifier"] autorelease];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

        UIImageView *whiteView = [[UIImageView alloc] initWithFrame:CGRectMake((projectsTable.frame.size.width/2)-150, 4, 204.8, 153.6)];
        whiteView.tag = 111;
        whiteView.backgroundColor = [UIColor whiteColor];

        [cell.contentView addSubview:whiteView];

        [whiteView release];
        cell.accessoryType = UITableViewCellAccessoryNone;
        cell.textLabel.hidden = YES;
    }

    UIImageView* iView = (UIImageView*) [cell.contentView viewWithTag:111];


    if([currSection isEqualToString:@"composer"]) {

        MySlide *s = [slidesArray objectAtIndex:indexPath.row];

        if([s.slideImage isEqualToString:@""] || s.slideImage == nil) {

            //no custom image in this cell - go with default background image
            iView.image = [UIImage imageNamed:@"cellback2.png"];
        }
        else {

            cell.layer.shouldRasterize = YES;
            cell.layer.rasterizationScale = [UIScreen mainScreen].scale;

            // use the image path as the cache key
            UIImage *theImage = [_imageCache objectForKey:s.slideImage];
            if (theImage == nil) {

                // load the image and save into the cache
                theImage = [UIImage imageWithContentsOfFile:s.slideImage];
                theImage = [self imageWithImage:theImage CovertToSize:CGSizeMake(204.8, 153.6)];

                [_imageCache setObject:theImage forKey:s.slideImage];
            }

            iView.image = theImage;
        }   
    }
}

@end

As a general rule, tableView:cellForRowAtIndexPath: is a method you need to get out of fast, so loading images from disk should be avoided wherever possible.

Ell Neal
  • 6,014
  • 2
  • 29
  • 54
  • Thanks - this also works and will surely come in handy when dealing with more images than I currently allow my users to add to the slideshow. – PinkFloydRocks Feb 06 '12 at 13:09
0

There is also a delay the first time each UIImage is displayed. See this post for details on prompting the work at cache time rather than display time:

Setting image property of UIImageView causes major lag

Community
  • 1
  • 1
0

Change the code as per below...

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];

if (cell == nil) 
{
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MyIdentifier"] autorelease];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    UIImageView *whiteView = [[UIImageView alloc] initWithFrame:CGRectMake((projectsTable.frame.size.width/2)-150, 4, 204.8, 153.6)];
    whiteView.tag = 111;
    whiteView.backgroundColor = [UIColor whiteColor];

    [cell.contentView addSubview:whiteView];

    [whiteView release];
    cell.accessoryType = UITableViewCellAccessoryNone;
    cell.textLabel.hidden = YES;

}

UIImageView* iView = (UIImageView*) [cell.contentView viewWithTag:111];


if([currSection isEqualToString:@"composer"])
{
    MySlide *s = [slidesArray objectAtIndex:indexPath.row];

    if([s.slideImage isEqualToString:@""] || s.slideImage == nil)
    {
        //no custom image in this cell - go with default background image

        iView.image = [UIImage imageNamed:@"cellback2.png"];
    }
    else
    {
        cell.layer.shouldRasterize = YES;
        cell.layer.rasterizationScale = [UIScreen mainScreen].scale;

        iView.image = [UIImage imageWithContentsOfFile:s.slideImage];
        iView.image = [self imageWithImage:iView.image CovertToSize:CGSizeMake(204.8,153.6)];

    }   
  }
}
vishy
  • 3,241
  • 1
  • 20
  • 25
  • The scrolling still stops for a bit when a cell loads an image from the Documents-folder.. Could this stop be associated with the actual loading of imagedata? The original image is 1024x768 but as you see from my code is resized to correspond with the cell's size - is this maybe causing the stop? – PinkFloydRocks Feb 06 '12 at 12:17
  • @PinkFloydRocks You will need to cache the images as well, store them in an `NSArray` or `NSDictionary` in your `UIViewController` subclass (after you have resized them). – Ell Neal Feb 06 '12 at 12:22
  • @EllNeal I got it working by generating a thumbnail image as well as the main image for the slide. So it probably was the size of the image and its data that caused the stop. But just out of curiosity, could you provide a small example of how you would cache the images? Do you cache their data in an array and use this data when creating the image? – PinkFloydRocks Feb 06 '12 at 12:26
  • @PinkFloydRocks I'll post an answer – Ell Neal Feb 06 '12 at 12:29