iOS:滚动UITableView时填写应用程序崩溃/内存

时间:2013-02-04 07:53:53

标签: ios uitableview hjcache

我的应用程序中的一个视图显示了图像列表。当我多次滚动该列表时,我的应用程序崩溃了。我用仪器对它进行了分析,看起来列表的单元格在滚动列表时占用了更多的内存。

从tableView返回时,自定义UITableCell是否应该“自动释放”:cellForRowAtIndexPath :? (如果我这样做,我在iOS 4.3上崩溃/它在iOS 5.0和6.1中很好)

这个自定义UITableCell有几张图片被绘制到'contentView'中。这些图片实际上是自定义UIButton,我在其中设置了背景图像。

使用HJManagedImageV

管理图片

自定义UIButton的代码:

@implementation ProductTileButtonIpad

@synthesize product;

- (id)initWithFrame:(CGRect)frame andProduct:(Product *)aProduct {

    if (self = [super initWithFrame:frame]) {

        self.product = aProduct;

        self.productTileView = [[[HJManagedImageV alloc] initWithFrame:self.frame] autorelease];
        self.productTileView.callbackOnSetImage = self;
        self.productTileView.url = some picture url

        [[ImageManager instance] manage:self.productTileView];
    }

    return self;
}


#pragma mark -
#pragma mark HJManagedImageV delegate

-(void) managedImageSet:(HJManagedImageV*)mi {

    [self setBackgroundImage:mi.image forState:UIControlStateNormal];
}

-(void) managedImageCancelled:(HJManagedImageV*)mi {
}


- (void)dealloc {

    NSLog(@"deallocating ProductTileButtonIpad");

    [self.product release];
    [self.productTileView release];

    [super dealloc];
}

@end

自定义单元格的代码

@implementation ProductGridCellIpad

@synthesize products, parentController;

- (void)initializeWithProducts:(NSMutableArray *)productsToShow{

    self.products = productsToShow;

    // clear possible old subviews
    for (UIView *v in self.contentView.subviews) {
        [v removeFromSuperview];
    }

    NSInteger width = 240;
    NSInteger height = 240;

    Product *product0 = [products objectAtIndex:0];

    self.productTile0 = [[[ProductTileButtonIpad alloc] initWithFrame:CGRectMake(12, 12, width, height) andProduct:product0] autorelease];

    [self.productTile0 addTarget:self.parentController action:@selector(selectedProduct:) forControlEvents:UIControlEventTouchUpInside];

    [self.contentView addSubview:self.productTile0];

    [self.productTile0 release];

    if ([self.products count] > 1) {

        Product *product1 = [products objectAtIndex:1];

        self.productTile1 = [[[ProductTileButtonIpad alloc] initWithFrame:CGRectMake(12 + width + 12, 12, width, height) andProduct:product1] autorelease];

        [self.productTile1 addTarget:self.parentController action:@selector(selectedProduct:) forControlEvents:UIControlEventTouchUpInside];

        [self.contentView addSubview:self.productTile1];

        [self.productTile1 release];
    }

    if ([self.products count] > 2) {

        Product *product2 = [products objectAtIndex:2];

        self.productTile2 = [[[ProductTileButtonIpad alloc] initWithFrame:CGRectMake(2*(12 + width) + 12, 12, width, height) andProduct:product2] autorelease];

        [self.productTile2 addTarget:self.parentController action:@selector(selectedProduct:) forControlEvents:UIControlEventTouchUpInside];

        [self.contentView addSubview:self.productTile2];

        [self.productTile2 release];
    }
}

- (void)dealloc {

    NSLog(@"deallocating ProductGridCellIpad");

    if(self.products)
        [self.products release];

    if(self.productTile0)
        [self.productTile0 release];

    if(self.productTile1)
        [self.productTile1 release];

    if(self.productTile2)
        [self.productTile2 release];

    [super dealloc];
}

@end

这是创建单元格的代码:

    NSString *productGridCellIpadIdentifier = @"ProductGridCellIpadIdentifier";

    ProductGridCellIpad *cell = [tableView dequeueReusableCellWithIdentifier:productGridCellIpadIdentifier];

    if(cell == nil) {

        cell = [[ProductGridCellIpad alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:productGridCellIpadIdentifier];

        [cell setFrame:CGRectMake(0, 0, self.view.frame.size.width, 244)];
    }

    [cell setParentController:self];
    [cell initializeWithProducts:products];

    return cell;

现在,代码在iOS 4.3上立即崩溃。它适用于iOS 5和6,但在使用/滚动表格后,应用程序仍会崩溃。

我不使用ARC。

我在dealloc方法中添加了一些NSLog来查看发生了什么,我可以看到很多“解除分配ProductTileButtonIpad”,但我从未看到“解除分配ProductGridCellIpad”

我的应用程序很容易达到400Mb的内存使用量。

我在这里做错了什么?

如果你们中的一些人有任何想法,那么可以帮助我理解它的想法将非常感激:)

2 个答案:

答案 0 :(得分:2)

单元格被重用,因此在滚动时不应该看到“dealloc ProductGridCellIpad”。而是验证回收是否真的有效,或者您是否一直在创建新的单元格:

ProductGridCellIpad *cell = [tableView dequeueReusableCellWithIdentifier:productGridCellIpadIdentifier];

if(cell == nil) {
    cell = [[ProductGridCellIpad alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:productGridCellIpadIdentifier];
    [cell setFrame:CGRectMake(0, 0, self.view.frame.size.width, 244)];
    NSLog("Cell created");
}
else {
    NSLog("Cell recycled");
}

如果没关系,我会检查发布。例如,你有“self.productTile2”自动释放和释放,这可能会混淆内存管理。

另外,我会仔细检查“parentController”,这可能会阻止事件被释放。您需要将其设置为nil。

答案 1 :(得分:1)

是的,使用autorelease时,您显然需要alloc] init..您的手机 dequeueReusableCellWithIdentifier返回自动释放的。