Cody
Cody

Reputation: 840

Hanging when loading async image in UITableViewCell

I'm programming my first iOS application and I'm trying to asynchronously load images into my UITableViewCells. I'm loading the images in the background into a NSMutableArray, which is then retrieved at the cellForRowAtIndexPath method. The cells are able to load the images, but crashes on the ~5th cell and gives me one of two different errors:

SIGABRT at the @synthesize line in ApplicationCell.m with malloc: * error for object 0x6c30e60: double free

or just enters gdb and points at iconView.image = newIcon; (Thread 1).

I've declared the NSMutableArray *imageArray in the @interface of the table view controller and set it as a @property, then @synthesize'd it:

@synthesize searchArray;
...
- (void)viewDidLoad {
    [super viewDidLoad];
    ...
    self.imageArray = [[NSMutableArray alloc] initWithCapacity:8]; //<-- Am I doing this correctly?
    for (int i=0; i < 8; i++) {
        [self.imageArray addObject:[UIImage imageNamed:@"empty.png"]];
    }
    ...
}

There will be a maximum of 8 images loaded in the background, which will be placed inside imageArray:

- (void)requestFinishedImage:(ASIFormDataRequest*)request {
    //image request
    NSData *responseData = [request responseData];
    NSIndexPath *index = [NSIndexPath indexPathForRow:request.tag inSection:0];
    UIImage *image = [[UIImage alloc] initWithData:responseData];
    NSLog(@"requested Image with tag: %d",request.tag);
    [imageArray replaceObjectAtIndex:request.tag withObject:image];
    ApplicationCell *cell = (ApplicationCell *)[self.tableView cellForRowAtIndexPath:index];
    [cell setIcon2:image];
    cell.icon = image;
    [image release];
}

Here is the cellForRowAtIndexPath:

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

    static NSString *CellIdentifier = @"Cell";

    ApplicationCell *cell = (ApplicationCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        [self.cellNib instantiateWithOwner:self options:nil];
        cell = tmpCell;
        self.tmpCell = nil;
    }
    UIImage *image;
    NSUInteger row = [indexPath row];

    [cell setItem2: [[searchArray objectAtIndex:row] objectForKey:@"item"]];
    [cell setPrice2: cell.price];
    image = [imageArray objectAtIndex:row];
    NSLog(@"num elements in imageArray = %d, loading: %d",[imageArray count], row);
    [cell setIcon2: image];
[image release];
    return cell;
}

And here are my ApplicationCell.h and ApplicationCell.m

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface ApplicationCell : UITableViewCell
{

    UIImage *icon;
    NSString *item;
    NSString *price;
    IBOutlet UIImageView *iconView;
    IBOutlet UILabel *itemLabel;
    IBOutlet UILabel *priceLabel;
}
- (void)setIcon2:(UIImage *)newIcon;
- (void)setItem2:(NSString *)newItem;
- (void)setPrice2:(NSString *)newPrice;

@property(retain) UIImage *icon;
@property(retain) NSString *item;
@property(retain) NSString *price;

@end

ApplicationCell.m

#import "ApplicationCell.h"

@implementation ApplicationCell

@synthesize icon, item, price;

- (void)setIcon2:(UIImage *)newIcon
{
    [self setIcon:newIcon];
    iconView.opaque = YES;
    iconView.image = newIcon;
}
- (void)setItem2:(NSString *)newItem
{
    [self setItem:newItem];
    itemLabel.text = newItem;
}

- (void)setPrice2:(NSString *)newPrice
{
    [self setPrice:newPrice];
    priceLabel.text = newPrice;
}


- (void)dealloc
{
    [icon release];
    [item release];
    [price release];

    [iconView release];
    [itemLabel release];
    [priceLabel release];

    [super dealloc];
}

@end

There are probably some mistakes in the code since this is my first time trying an iOS application, but please let me know so I can learn! I've been stuck on this async loading issue for too long.. Any help is appreciated!

Upvotes: 0

Views: 624

Answers (1)

Jeff Kelley
Jeff Kelley

Reputation: 19071

Take out the [image release] call in -tableView:cellForRowAtIndexPath:. You didn't retain it there,so you don't need to release it. If you use Xcode's static analyzer, it should find memory errors like this.

Upvotes: 2

Related Questions