我使用以下代码使用以下代码从服务器加载图像。当我滚动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];
}
在ViewController类中加载图像
- (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;
}
我该如何解决这个问题? 我附上了它的快照分析屏幕截图。这些非对象消耗了大量的内存是什么?
答案 0 :(得分:5)
这是错误:
NSString *reuseIdentifier = [NSString stringWithFormat:@"%d",indexPath.row];
似乎你不是在重复使用单元格,而是为表格的每一行创建一个新单元格! 这样,如果您需要查看100或1000行,则可以创建/分配100或1000个对象单元格。
这不是UITableView的正确用法。 UITableView的“神奇之处”在于它重用了单元格,它只创建并分配了所需的少量单元格......
e.g。考虑到你的桌子有一个480像素的垂直空间,你的单元格高度是100像素,那么你只需要5个单元格,不需要创建1000个单元格,你只能看到5个单元格...
所以神奇的是当你向上滚动它并且它已经离开屏幕并重置它的内容(图像和文本)并将其用于用户将要看到的新呼叫时,重用已经分配的单元格...
答案 1 :(得分:2)
虽然细胞重用不是问题,但泄漏的细胞是:
cell = [[ListCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
你忘了autorelease
这个,所以你很快就会泄漏细胞。你确实记得自动释放cell1
。