cellForRowAtIndexPath управление памятью - PullRequest
2 голосов
/ 14 января 2012

Итак, вот код для моего 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).

У меня нет переменных, настроенных на авто-релиз (в основном потому, что я пока не совсем понимаю авто-релиз)

В любом случае, при прокрутке приложения оно будет постепенно замедляться (в основном из-заUIImage, но также частично из-за меток и рамок).

Есть ли способ лучше управлять моей памятью?Кроме того, есть ли лучший способ кодирования этого?Я думал о создании массива UITableViewCells и просто доступ к ним через cellForRowAtIndexPath.

Так что я хотел бы получить некоторые предложения, спасибо, ребята.

Ответы [ 5 ]

12 голосов
/ 14 января 2012

Вы пропускаете много ярлыков там.Каждый раз, когда вы выделяете / инициируете новый ярлык, вам нужно его освободитьВ настоящее время вы повторно используете одну и ту же переменную метки несколько раз, назначая ей новый объект метки, не освобождая старый.

Вместо того, чтобы ставить [выпуск метки] в конце, ставьте [выпуск метки] после каждого[cell addSubview: label];

Ваша следующая проблема - вы неправильно поняли, как работает переработка табличных ячеек.Объекты UITableCell снова и снова используются в таблице, вот почему вы делаете этот бит:

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

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

В сущности, это говорит о том, что «проверьте, доступна ли ячейка, и если нет, то создайте новую».Когда ячейка используется повторно, она сохраняет все старые материалы, которые вы добавили в нее.Поэтому, когда вы добавляете эти метки и представление изображения в ячейку, они остаются в этой ячейке при следующем использовании и в следующий раз.

Но поскольку вы снова добавляете метки каждый раз, когда ячейка повторноиспользуется, он создает несколько копий меток, поэтому во второй раз, когда отображается ячейка, у нее в два раза больше меток, а в следующий раз - в 3 раза и т. д.Вы не можете видеть дубликаты, потому что они находятся в одном и том же месте, но они используют память и замедляют работу таблицы.

Вам нужно переместить код, где вы добавляете новые представления вячейка внутри оператора if (cell == nil) {...} ", поэтому метки добавляются только один раз при создании ячейки.

Конечно, это означает, что каждая ячейка будет иметь одинаковый тексти изображение, которое вам не нужно, поэтому вам нужно разделить логику, в которой вы устанавливаете текст и изображения, и поместить их после оператора if.Таким образом, вы создаете метки только один раз, но устанавливаете текст каждый раз, когда они отображаются в другой строке таблицы.Это немного сложно, потому что у вас больше нет ссылок на ярлыки, но вы можете сделать это, установив уникальные теги на ярлыках, чтобы вы могли найти их снова.

Вот исправленная версия свсе утечки удалены:

- (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;
} 
5 голосов
/ 14 января 2012

Чтобы повысить эффективность использования памяти и добиться более плавной прокрутки, вы должны создать пользовательский подкласс UITableViewCell, который содержит пользовательский UIView в качестве подпредставления contentView UITableViewCell. Вы должны рисовать в этом пользовательском представлении, используя -drawRect: . Наличие большой иерархии представлений требует большого объема памяти, в отличие от одного представления, для которого весь контент рисуется напрямую.

Примеры AppleView TableViewSuite на самом деле содержат пример этого прямого рисования. Скачать проект можно здесь:

http://developer.apple.com/library/ios/#samplecode/TableViewSuite/Introduction/Intro.html

Посмотрите пятый пример, чтобы получить представление о том, как реализовать высокопроизводительное рисование ячейки табличного представления с малым объемом памяти в собственном проекте.

0 голосов
/ 23 января 2014

одним словом, причина утечки - дополнительная ссылка от addSubview.поэтому обязательно добавьте addSubview или удалите его перед добавлением нового.

0 голосов
/ 14 января 2012

Попробуйте установить статическую строку и используйте ее в следующих методах:

    static NSString *identifier = @"identifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier]autorelease];
0 голосов
/ 14 января 2012

Почему бы не построить свою ячейку в IB и создать подкласс UITableViewCell для своих нужд (3 UILabels и UIImageView)?У меня есть проекты со сложными ячейками таблицы, и эта система хорошо работает для меня.Держите код намного чище и проще в управлении.Если вам нужен рабочий пример, я могу отправить его вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...