cellForRowAtIndexPath内存管理

问题描述:

所以,这是我的cellForRowAtIndexPath的代码:

So, here's the code for my cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"identifier"];

    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"identifier"]autorelease];
    }

    NSInteger artistIndex = 1; // 1
    NSInteger albumIndex = 3;  // 3
    NSInteger dateIndex = 6;   // 6
    NSInteger imageIndex = 8;  // 5

    // ARTIST
    CGRect frame = CGRectMake(59, 11, 244, 13);
    UILabel *label = [[UILabel alloc]initWithFrame:frame];
    label.font = [UIFont boldSystemFontOfSize:13];
    label.textColor = [UIColor blackColor];
    label.text = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:artistIndex];
    [cell addSubview:label];

    // ALBUM (more like description...
    frame = CGRectMake(60, 30, 244, 11);
    label = [[UILabel alloc]initWithFrame:frame];
    label.font = [UIFont boldSystemFontOfSize:11];
    label.textColor = [UIColor darkGrayColor];
    label.text = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:albumIndex];
    [cell addSubview:label];

    // DATE
    frame = CGRectMake(59, 49, 244, 10);
    label = [[UILabel alloc]initWithFrame:frame];
    label.font = [UIFont fontWithName:@"Helvetica" size:10.0];
    label.textColor = [UIColor darkGrayColor];
    label.textAlignment = UITextAlignmentRight;
    label.text = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:dateIndex];
    [cell addSubview:label];

    // IMAGE
    UIImageView *imageView = [[UIImageView alloc]init];
    imageView.image = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:imageIndex];
    imageView.frame = CGRectMake(8,9,44,44);
    [imageView.layer setMasksToBounds:YES];
    [imageView.layer setCornerRadius:3.0];
    [[cell contentView] addSubview:imageView];

    [imageView release];
    [label release]; 

    return cell;
}

为了解释发生了什么,基本上它只是点击一个存储字符串的数组除了索引8(存储UIImage)之外的所有内容。

To explain what's going on, basically it just taps into an array that stores strings for everything except for index 8 (which stores a UIImage).

我没有设置自动释放的变量(主要是因为我真的不明白自动释放只是lol)

I have no variables set to autorelease (mostly because I don't really understand autorelease just yet lol)

无论如何,当滚动浏览应用程序时,它会逐渐减慢(主要是因为UIImage,但部分原因还在于标签和框架)。

Anyways, when scrolling through the app, it will slow down progressively (mostly because of the UIImage, but also in part because of the labels and frames).

无论如何更好地管理我的记忆?另外,有更好的编码方式吗?我正在考虑制作一个UITableViewCells数组,只是通过cellForRowAtIndexPath访问它们。

Is there anyway to manage my memory better? Also, is there a nicer way of coding this? I was thinking of making an array of UITableViewCells and just accessing those via cellForRowAtIndexPath.

所以我很想得到一些建议,谢谢你们。

So I would love for some suggestions, thanks guys.

你在那里泄漏了很多标签。每次分配/初始化新标签时,都需要释放它。目前,您通过为其分配一个新标签对象而不释放旧标签对象,多次重复使用相同的标签变量。

You're leaking a lot of labels there. Every time you alloc/init a new label you need to release it. Currently you are re-using the same label variable several times by assigning it a new label object without releasing the old one.

而不是将[标签发布]放在结束,在每个[cell addSubview:label]之后放置[标签发布];

Instead of putting your [label release] at the end, put [label release] after every [cell addSubview:label];

你的下一个问题是你误解了表格单元的回收是如何工作的。 UITableCell对象在表中反复使用,这就是为什么这样做的原因:

Your next problem is you've misunderstood how the table cell recycling works. UITableCell objects are reused over and over again within a table, that why you do this bit:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"identifier"];

if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"identifier"]autorelease];
}

这基本上是说检查是否有可用的单元格,如果没有创建新的一个。重新使用单元格时,它会保留您添加到其中的所有旧内容。因此,当您将这些标签和图像视图添加到单元格时,它们会在下次使用时保留在该单元格中,并在下次使用时保留在该单元格中。

That's basically saying "check if there's a cell available, and if not create a new one". When a cell is re-used it keeps all the old stuff you've added to it. So when you add those labels and image view to the cell, they stay in that cell the next time it is used, and the next time.

但是因为您添加了每次重复使用单元格时再次标记,它会构建多个标签副本,因此第二次显示单元格时,标签的数量是标签的两倍,下一次是标签的3倍,依此类推。您无法看到重复项,因为它们位于完全相同的位置,但是它们会占用内存并减慢您的桌面速度。

But because you add the labels again each time the cell is re-used, it builds up multiple copies of the labels, so the second time the cell is displayed it has twice as many labels, and the next time 3 times as many, and so on. You can't see the duplicates because they're in exactly the same place, but they're there using up memory and slowing your table down.

您需要移动您在if(cell == nil){...}语句中向单元格添加新视图的代码,因此标签仅在创建单元格时添加一次。

You need to move the code where you append new views to the cell inside the "if (cell == nil) { ... }" statement, so the labels are only added once when the cell is created.

当然这意味着每个单元格都有相同的文本和图像,这是您不想要的,因此您需要拆分设置文本和图像的逻辑并将其放在if语句之后。这样,您只需创建一次标签,但每次在不同的表格行中显示时都会设置文本。这有点棘手,因为你没有对标签的引用,但是你可以通过在标签上设置唯一标签来做到这一点,这样你就可以再次找到它们。

Of course that means that every cell will have the same text and image, which you don't want, so you need to split out the logic where you set the text and images and put it after the if statement. That way you only create the labels once but you set the text each time they are displayed in a different table row. That's a bit tricky because you don't have the references to the labels any more, but you can do it by setting unique tags on the labels so you can find them again.

这是一个已清除所有泄漏的清理版本:

Here's a cleaned-up version with all the leaks removed:

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

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"identifier"];

    NSInteger artistTag = 1;
    NSInteger albumTag = 2;
    NSInteger dateTag = 3;
    NSInteger imageTag = 4;

    if (cell == nil) {

        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"identifier"]autorelease];

        // ARTIST
        CGRect frame = CGRectMake(59, 11, 244, 13);
        UILabel *label = [[UILabel alloc]initWithFrame:frame];
        label.font = [UIFont boldSystemFontOfSize:13];
        label.textColor = [UIColor blackColor];
        label.tag = artistTag;
        [cell addSubview:label];
        [label release];

        // ALBUM (more like description...
        frame = CGRectMake(60, 30, 244, 11);
        label = [[UILabel alloc]initWithFrame:frame];
        label.font = [UIFont boldSystemFontOfSize:11];
        label.textColor = [UIColor darkGrayColor];
        label.tag = albumTag;
        [cell addSubview:label];
        [label release];

        // DATE
        frame = CGRectMake(59, 49, 244, 10);
        label = [[UILabel alloc]initWithFrame:frame];
        label.font = [UIFont fontWithName:@"Helvetica" size:10.0];
        label.textColor = [UIColor darkGrayColor];
        label.textAlignment = UITextAlignmentRight;
        label.tag = dateTag;
        [cell addSubview:label];
        [label release];

        // IMAGE
        UIImageView *imageView = [[UIImageView alloc]init];
        imageView.frame = CGRectMake(8,9,44,44);
        imageView.tag = imageTag;
        [imageView.layer setMasksToBounds:YES];
        [imageView.layer setCornerRadius:3.0];
        [[cell contentView] addSubview:imageView];
        [imageView release];
    }

    NSInteger artistIndex = 1; // 1
    NSInteger albumIndex = 3;  // 3
    NSInteger dateIndex = 6;   // 6
    NSInteger imageIndex = 8;  // 5

    ((UILabel *)[cell viewWithTag:artistTag]).text = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:artistIndex];

    ((UILabel *)[cell viewWithTag:albumTag]).text = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:albumIndex];

    ((UILabel *)[cell viewWithTag:dateTag]).text = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:dateIndex];

    ((UIImageView *)[cell viewWithTag:imageTag]).image = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:imageIndex];


    return cell;
}