2012-04-06 79 views
1

我使用以下代码从服务器使用以下代码加载图像。当我滚动UITableView应用程序崩溃。应用程序在加载图像时显示低内存警告和崩溃?

AsynchrohousImageView类.m文件

- (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]; 
} 

在视图控制器类加载图像

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



static NSString *reuseIdentifier [email protected]"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; 
} 

我怎么能解决这个问题? 我附上了heapshot分析的屏幕截图。这里非对象消耗如此多的内存是什么? Heap Shot Analysis

回答

5

这是错误:

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

看来你是不重用细胞,但对于你的表的每一行创建一个新的细胞! 这样如果你需要看100或1000行,你可以创建/分配100或1000个对象单元。

这不是正确使用UITableView。 UITableView的“魔力”在于它重复使用了单元格,它只是创建并分配所需的次要单元格数量...

例如,考虑一下你的桌子有480像素的垂直空间,而你的单元格的高度是100像素,那么你只需要5个单元格的时间,不需要创建1000个单元格,在时间点你只能看到5个单元格...

所以神奇的是,当您向上滚动并重新开始分配的单元格时,它将重新启动它的内容(图像和文本)并将其用于用户将看到的新呼叫。 ..

+0

即使我已将其更改为静态NSString * CellIdentifier = @“CellIdentifier”,那么应用程序也会崩溃bcoz的内存警告 – Bhoomi 2012-04-06 11:30:04

+1

未能重用单元格不会导致表视图保留无限数量的单元格。这只是意味着你会按需要重新创建它们,这通常比较慢。正如Bhoomi所说,这不应该解决内存问题。 – 2012-04-06 12:48:34

+0

rob是正确的,当然,我给他一个+1 ...我刚刚停下来看起来对我来说是错误的第一行代码...并且显示我们没有以正确的方式使用表格。 。你应该看看一些苹果样本,并了解它是如何工作的... – meronix 2012-04-06 14:34:04

2

虽然单元复用是没有问题的,泄漏的细胞是:

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

你忘了这autorelease,让你乐非常快速地获得细胞。你确实记得自动发布cell1

相关问题