cellForRowAtIndexPath 内存管理 [英] cellForRowAtIndexPath memory management

查看:16
本文介绍了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).

我没有将变量设置为自动释放(主要是因为我还不太了解自动释放,哈哈)

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.

不要将 [label release] 放在末尾,而是将 [label release] 放在每个 [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;
} 

这篇关于cellForRowAtIndexPath 内存管理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆