iosdev1111
iosdev1111

Reputation: 1112

Application shows low memory warning and crashes while loading images?

I am using following code for loading images from server using following code.When i scroll UITableView application crashes.

AsynchrohousImageView class .m file

- (void)dealloc {
[connection cancel]; //in case the URL is still downloading
[connection release];
[data release]; 
[_imageView release];
[_activityIndicator release];
[super dealloc];
}

- (void)loadImageFromURL:(NSURL*)url 
   defaultImageName:(NSString *)defaultImageName 
   showDefaultImage:(BOOL)defaultImageIsShown 
   showActivityIndicator:(BOOL)activityIndicatorIsShown 
   activityIndicatorRect:(CGRect)activityIndicatorRect
   activityIndicatorStyle:(UIActivityIndicatorViewStyle)activityIndicatorStyle {

if (connection!=nil) { [connection release]; }  if (data!=nil) { [data release]; }

 if ([[self subviews] count]>0) {
    [[[self subviews] objectAtIndex:0] removeFromSuperview]; // }

 if (defaultImageIsShown) {
      self.imageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:defaultImageName]] autorelease];
} else {
    self.imageView = [[[UIImageView alloc] init] autorelease];
}


[self addSubview:_imageView];
_imageView.frame = self.bounds;
[_imageView setNeedsLayout];   
[self setNeedsLayout];

if (activityIndicatorIsShown) {

    self.activityIndicator = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:activityIndicatorStyle] autorelease];
    [self addSubview:_activityIndicator];
    _activityIndicator.frame = activityIndicatorRect;
    _activityIndicator.center = CGPointMake(_imageView.frame.size.width/2, _imageView.frame.size.height/2);
    [_activityIndicator setHidesWhenStopped:YES];
    [_activityIndicator startAnimating];
}


NSURLRequest* request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
 }


- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData  *)incrementalData {
if (data==nil) { data = [[NSMutableData alloc] initWithCapacity:2048]; } 
[data appendData:incrementalData];
  }

  - (void)connectionDidFinishLoading:(NSURLConnection*)theConnection {
  [connection release];
  connection=nil;

   _imageView.image = [UIImage imageWithData:data];

if (_activityIndicator) {
    [_activityIndicator stopAnimating];
}

[data release];     data=nil;
}


- (UIImage*) image {
UIImageView* iv = [[self subviews] objectAtIndex:0];
return [iv image];
}

In ViewController Class Which loads image

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



static NSString *reuseIdentifier =@"CellIdentifier";
    ListCell *cell = (ListCell *)[tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
    if (cell==nil) {
        cell = [[ListCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
        NSMutableDictionary *dicResult = [arrResults objectAtIndex:indexPath.row];

    NSURL *url=[NSURL URLWithString:[dicResult objectForKey:@"Image"]];
    AsynchronousImageView *asyncImageView = [[AsynchronousImageView alloc] initWithFrame:CGRectMake(5, 10,80,80)];
    [asyncImageView loadImageFromURL:url
                    defaultImageName:@"DefaultImage.png"
                    showDefaultImage:NO
               showActivityIndicator:YES
               activityIndicatorRect:CGRectMake(5, 10,30,30)
              activityIndicatorStyle:UIActivityIndicatorViewStyleGray]; // load our image with URL asynchronously

    [cell.contentView addSubview:asyncImageView];   
    // cell.imgLocationView.image = [UIImage imageNamed:[dicResult valueForKey:@"Image"]];
    [asyncImageView release];

}

if([arrResults count]==1)

{
    UITableViewCell *cell1=[tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
    if(cell1==nil)
        cell1=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier] autorelease];
    NSMutableDictionary *dicResult = [arrResults objectAtIndex:0];
    cell1.textLabel.text=[dicResult valueForKey:@"NoResults"];
    return cell1;
}
else
{
NSMutableDictionary *dicResult = [arrResults objectAtIndex:indexPath.row];
NSString *title = [NSString stringWithFormat:@"%@ Bedrooms-%@", [dicResult valueForKey:KEY_NUMBER_OF_BEDROOMS],[dicResult valueForKey:KEY_PROPERTY_TYPE]];
NSString *strAddress = [dicResult valueForKey:KEY_DISPLAY_NAME];
NSString *address = [strAddress stringByReplacingOccurrencesOfString:@", " withString:@"\n"];
NSString *price = [dicResult valueForKey:KEY_PRICE];
NSString *distance = [dicResult valueForKey:KEY_DISTANCE];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

        cell.lblTitle.text = title;
cell.lblAddress.text = address;
if ([price length]>0) {
    cell.lblPrice.text = [NSString stringWithFormat:@"£%@",price];
}else{
    cell.lblPrice.text = @"";
}
if ([distance length]>0) {
    cell.lblmiles.text = [NSString stringWithFormat:@"%.2f miles",[distance floatValue]];
}else{
    cell.lblmiles.text = @"";
}


}
return cell;
}

How can i resolve this? I have attached heapshot analysis screen shot of it.Here non Object consumes so much of memory what is that?Heap Shot Analysis

Upvotes: 1

Views: 723

Answers (2)

Rob Napier
Rob Napier

Reputation: 299605

While cell reuse is not the problem, leaking cells is:

cell = [[ListCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];

You forgot to autorelease this, so you're leaking cells very quickly. You did remember to autorelease cell1.

Upvotes: 2

meronix
meronix

Reputation: 6176

this is the error:

NSString *reuseIdentifier = [NSString stringWithFormat:@"%d",indexPath.row];

it seems you are NOT reusing cells, but creating a new cell for every row of your table!!! this way if you need to see 100 or 1000 rows, you create/allocate 100 or 1000 object cells.

that's not the right use of a UITableView. the "magic" of UITableView is that it reuse cells, and it just creates and allocates just the minor number of cells needed...

e.g. consider you have a vertical spaces of 480 pixels for your tables, and your cells are 100 pixel height, then you just need 5 cells for time, no need to create 1000 cells, you can see just 5 cells at time...

so the magic is to reuse an already allocated cell when you scroll it up and it goes out of screen, and to reset it's contents (images and text) and to use it for the new call that user is going to see down...

Upvotes: 5

Related Questions