Reputation: 1112
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?
Upvotes: 1
Views: 723
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
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