UITableView повторяющиеся ячейки при прокрутке - PullRequest
3 голосов
/ 27 июля 2011

Когда я прокручиваю свой UITableView, по какой-то причине ячейки кажутся нарисованными друг над другом. Если я загружу свое приложение, ячейка будет выглядеть примерно так:

enter image description here

И после прокрутки этой ячейки на экране несколько раз, она начнет выглядеть так:

enter image description here

Как видите, что-то, что я не могу понять, идет не так. Есть идеи?

РЕДАКТИРОВАТЬ: cellForRowAtIndexPath

static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    NSString *vaultsPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Vaults"];

    NSString *dictionaryPath = [NSString stringWithFormat:@"%@/%@",
                                vaultsPath,
                                [self.vaults objectAtIndex:indexPath.row]];
    NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:dictionaryPath];
    cell = [AHCellCreation createCellWithDictionary:dictionary Cell:cell];

    return cell;

AHCellCreation + createCellWithDictionary: Ячейка:

//General cell design, same every time
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = CGRectMake(0, 0, 320, 82);
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithHue:0 saturation:0 brightness:0.91 alpha:1] CGColor], (id)[[UIColor colorWithHue:0 saturation:0 brightness:0.85 alpha:1] CGColor], nil];
[cell.contentView.layer addSublayer:gradient];

UIView *topLine = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 1)];
topLine.backgroundColor = [UIColor colorWithHue:0 saturation:0 brightness:0.97 alpha:1.0];
[cell addSubview:topLine];

UIView *bottomLine = [[UIView alloc] initWithFrame:CGRectMake(0, 81, 320, 1)];
bottomLine.backgroundColor = [UIColor colorWithHue:0 saturation:0 brightness:0.64 alpha:1.0];
[cell addSubview:bottomLine];

//Preview Image
NSString *previewImageFilePath = [dictionary objectForKey:@"PreviewImage"];

UIImageView *previewImageView = [[UIImageView alloc] initWithFrame:CGRectMake(9, 9, 64, 64)];
previewImageView.image = [UIImage imageWithContentsOfFile:previewImageFilePath];
[cell addSubview:previewImageView];

//Creation date 
UILabel *createdOnLabel = [[UILabel alloc] init];
createdOnLabel.frame = CGRectMake(85, -5, 303, 41);
createdOnLabel.text = @"Created on";
createdOnLabel.backgroundColor = [UIColor clearColor];
createdOnLabel.textAlignment = UITextAlignmentLeft;
createdOnLabel.font = [UIFont systemFontOfSize:12];
createdOnLabel.textColor = [UIColor colorWithHue:0.59 saturation:0.29 brightness:0.47 alpha:1.0];
[cell addSubview:createdOnLabel];

NSDate *creationDate = [dictionary objectForKey:@"CreationDate"];
UILabel *creationDateLabel = [[UILabel alloc] initWithFrame:CGRectMake(85, 0, 303, 82)];
creationDateLabel.text = [AHCellCreation createReadableDateFromDate:creationDate];
creationDateLabel.backgroundColor = [UIColor clearColor];
creationDateLabel.textAlignment = UITextAlignmentLeft;
creationDateLabel.font = [UIFont boldSystemFontOfSize:28];
creationDateLabel.textColor = [UIColor colorWithHue:0.59 saturation:0.29 brightness:0.47 alpha:1.0];
[cell addSubview:creationDateLabel];

//Opening date
NSDate *notificationDate = [dictionary objectForKey:@"NotificationDate"];

NSDate *earliest = [notificationDate earlierDate:[NSDate date]];
BOOL notificationPassed;
if (earliest == [NSDate date]) {
    notificationPassed = YES;
}
else {
    notificationPassed = NO;
}

UILabel *notificationDateLabel = [[UILabel alloc] initWithFrame:CGRectMake(85, 47, 303, 41)];
if (notificationPassed == NO) {
    notificationDateLabel.text = @"To be opened";
}
else {
    notificationDateLabel.text = @"Opened on";
}
notificationDateLabel.backgroundColor = [UIColor clearColor];
notificationDateLabel.textAlignment = UITextAlignmentLeft;
notificationDateLabel.font = [UIFont systemFontOfSize:12];
notificationDateLabel.textColor = [UIColor colorWithHue:0.59 saturation:0.29 brightness:0.47 alpha:1.0];
[cell addSubview:notificationDateLabel];

UILabel *notificationDateLabel2 = [[UILabel alloc] init];
notificationDateLabel2.frame = CGRectMake(164, 47, 303, 41);
notificationDateLabel2.text = [AHCellCreation createReadableDateFromDate:notificationDate];
notificationDateLabel2.backgroundColor = [UIColor clearColor];
notificationDateLabel2.textAlignment = UITextAlignmentLeft;
notificationDateLabel2.font = [UIFont boldSystemFontOfSize:12];
notificationDateLabel2.textColor = [UIColor colorWithHue:0.59 saturation:0.29 brightness:0.47 alpha:1.0];
[cell addSubview:notificationDateLabel2];


return cell;

Ответы [ 4 ]

6 голосов
/ 27 июля 2011

вы просто добавляете все больше и больше UILabels и т. Д. В свою ячейку при каждом ее отображении!

Вам необходимо отслеживать все, что вы добавляете в свою ячейку, чтобы убедиться, что вы добавляете их только один раз! Есть несколько способов сделать это, но я рекомендую создать подкласс UITableViewCell самостоятельно

Например, вот код для правильной работы созданногоOnLabel:

@interface AHTableViewCell : UITAbleViewCell {
    UILabel *createdOnLabel;
}

@end

@implementation AHTableViewCell

@end

Тогда ваш код cellForRowAtIndexPath становится

AHTableViewCell *cell = (AHTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[AHTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

и ваш код создания становится:

//Creation date
UILabel *createdOnLabel = [cell createdOnLabel];
if (nil == createdOnLabel) {
    createdOnLabel = [[UILabel alloc] init];
    createdOnLabel.frame = CGRectMake(85, -5, 303, 41);
    createdOnLabel.backgroundColor = [UIColor clearColor];
    createdOnLabel.textAlignment = UITextAlignmentLeft;
    createdOnLabel.font = [UIFont systemFontOfSize:12];
    createdOnLabel.textColor = [UIColor colorWithHue:0.59 saturation:0.29 brightness:0.47 alpha:1.0];
    [cell addSubview:createdOnLabel];
    [cell setCreatedOnLabel:createdOnLabel];
}
createdOnLabel.text = @"Created on";

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

2 голосов
/ 27 июля 2011

@ Интуиция Гомати была верной. Вы получаете здесь переработанную клетку:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

В этой ячейке уже есть все виды. Затем вы снова добавляете просмотры. Когда вы вернете ячейку из dequeueReusableCellWithIdentifier:, вам следует перенастроить ее (изменить значения полей текста и изображения), а не восстанавливать ее с нуля. В этом весь смысл многоразовых ячеек. Обязательно прочитайте Руководство по программированию табличного представления для получения полной информации.

2 голосов
/ 27 июля 2011

Полагаю, вы продолжаете добавлять некоторые представления в представление содержимого ячейки. Решение можно найти только после просмотра кода.

Edit:

На самом деле я дал решение для кода, который вы опубликовали. Но я бы также порекомендовал создать подкласс UITableViewCell в соответствии с предложением deanWombourne.

Да, мое предположение верно.

Сначала создайте cellForRowAtIndexPath следующим образом.

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

   NSString *vaultsPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Vaults"];
   NSString *dictionaryPath = [NSString stringWithFormat:@"%@/%@",
                            vaultsPath,
                            [self.vaults objectAtIndex:indexPath.row]];
   NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:dictionaryPath];

   cell = [AHCellCreation createCellWithDictionary:dictionary Cell:cell];

}
else
{
   NSString *vaultsPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Vaults"];

    NSString *dictionaryPath = [NSString stringWithFormat:@"%@/%@",
                                vaultsPath,
                                [self.vaults objectAtIndex:indexPath.row]];
    NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:dictionaryPath];
    cell = [AHCellCreation updateCellWithDictionary:dictionary Cell:cell];
}


return cell;

AHCellCreation + createCellWithDictionary: Ячейка:

//General cell design, same every time
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = CGRectMake(0, 0, 320, 82);
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithHue:0 saturation:0 brightness:0.91 alpha:1] CGColor], (id)[[UIColor colorWithHue:0 saturation:0 brightness:0.85 alpha:1] CGColor], nil];
[cell.contentView.layer addSublayer:gradient];

UIView *topLine = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 1)];
topLine.tag = 100;
topLine.backgroundColor = [UIColor colorWithHue:0 saturation:0 brightness:0.97 alpha:1.0];
[cell addSubview:topLine];

UIView *bottomLine = [[UIView alloc] initWithFrame:CGRectMake(0, 81, 320, 1)];
bottomLine.tag = 101;
bottomLine.backgroundColor = [UIColor colorWithHue:0 saturation:0 brightness:0.64 alpha:1.0];
[cell addSubview:bottomLine];

//Preview Image
NSString *previewImageFilePath = [dictionary objectForKey:@"PreviewImage"];

UIImageView *previewImageView = [[UIImageView alloc] initWithFrame:CGRectMake(9, 9, 64, 64)];
previewImageView.tag = 102;
previewImageView.image = [UIImage imageWithContentsOfFile:previewImageFilePath];
[cell addSubview:previewImageView];

//Creation date 
UILabel *createdOnLabel = [[UILabel alloc] init];
createdOnLabel.tag = 103;
createdOnLabel.frame = CGRectMake(85, -5, 303, 41);
createdOnLabel.text = @"Created on";
createdOnLabel.backgroundColor = [UIColor clearColor];
createdOnLabel.textAlignment = UITextAlignmentLeft;
createdOnLabel.font = [UIFont systemFontOfSize:12];
createdOnLabel.textColor = [UIColor colorWithHue:0.59 saturation:0.29 brightness:0.47 alpha:1.0];
[cell addSubview:createdOnLabel];

NSDate *creationDate = [dictionary objectForKey:@"CreationDate"];
UILabel *creationDateLabel = [[UILabel alloc] initWithFrame:CGRectMake(85, 0, 303, 82)];
creationDateLabel.tag = 104;
creationDateLabel.text = [AHCellCreation createReadableDateFromDate:creationDate];
creationDateLabel.backgroundColor = [UIColor clearColor];
creationDateLabel.textAlignment = UITextAlignmentLeft;
creationDateLabel.font = [UIFont boldSystemFontOfSize:28];
creationDateLabel.textColor = [UIColor colorWithHue:0.59 saturation:0.29 brightness:0.47 alpha:1.0];
[cell addSubview:creationDateLabel];

//Opening date
NSDate *notificationDate = [dictionary objectForKey:@"NotificationDate"];

NSDate *earliest = [notificationDate earlierDate:[NSDate date]];
BOOL notificationPassed;
if (earliest == [NSDate date]) {
    notificationPassed = YES;
}
else {
    notificationPassed = NO;
}

UILabel *notificationDateLabel = [[UILabel alloc] initWithFrame:CGRectMake(85, 47, 303, 41)];
notificationDateLabel.tag = 105;
if (notificationPassed == NO) {
    notificationDateLabel.text = @"To be opened";
}
else {
    notificationDateLabel.text = @"Opened on";
}
notificationDateLabel.backgroundColor = [UIColor clearColor];
notificationDateLabel.textAlignment = UITextAlignmentLeft;
notificationDateLabel.font = [UIFont systemFontOfSize:12];
notificationDateLabel.textColor = [UIColor colorWithHue:0.59 saturation:0.29 brightness:0.47 alpha:1.0];
[cell addSubview:notificationDateLabel];

UILabel *notificationDateLabel2 = [[UILabel alloc] init];
notificationDateLabel.tag = 106;
notificationDateLabel2.frame = CGRectMake(164, 47, 303, 41);
notificationDateLabel2.text = [AHCellCreation createReadableDateFromDate:notificationDate];
notificationDateLabel2.backgroundColor = [UIColor clearColor];
notificationDateLabel2.textAlignment = UITextAlignmentLeft;
notificationDateLabel2.font = [UIFont boldSystemFontOfSize:12];
notificationDateLabel2.textColor = [UIColor colorWithHue:0.59 saturation:0.29 brightness:0.47 alpha:1.0];
[cell addSubview:notificationDateLabel2];


return cell;

AHCellCreation + updateCellWithDictionary: Ячейка:

UIView *topLine = (UIView*)[cell viewWithTag:100];
topLine.backgroundColor = [UIColor colorWithHue:0 saturation:0 brightness:0.97 alpha:1.0];

UIView *bottomLine = (UIView*)[cell viewWithTag:101];
bottomLine.backgroundColor = [UIColor colorWithHue:0 saturation:0 brightness:0.64 alpha:1.0];

//Preview Image
NSString *previewImageFilePath = [dictionary objectForKey:@"PreviewImage"];

UIImageView *previewImageView = (UIImageView*)[cell viewWithTag:102];
previewImageView.image = [UIImage imageWithContentsOfFile:previewImageFilePath];

//Creation date 
UILabel *createdOnLabel = (UILabel*)[cell viewWithTag:103];
createdOnLabel.text = @"Created on";

NSDate *creationDate = [dictionary objectForKey:@"CreationDate"];
UILabel *creationDateLabel = (UILabel*)[cell viewWithTag:104];
creationDateLabel.text = [AHCellCreation createReadableDateFromDate:creationDate];

//Opening date
NSDate *notificationDate = [dictionary objectForKey:@"NotificationDate"];

NSDate *earliest = [notificationDate earlierDate:[NSDate date]];
BOOL notificationPassed;
if (earliest == [NSDate date]) {
    notificationPassed = YES;
}
else {
    notificationPassed = NO;
}

UILabel *notificationDateLabel = (UILabel*)[cell viewWithTag:105];
if (notificationPassed == NO) {
    notificationDateLabel.text = @"To be opened";
}
else {
    notificationDateLabel.text = @"Opened on";
}

UILabel *notificationDateLabel2 = (UILabel*)[cell viewWithTag:106];
notificationDateLabel2.text = [AHCellCreation createReadableDateFromDate:notificationDate];    

return cell;
1 голос
/ 27 июля 2011

Смысл повторного использования ячейки состоит в том, чтобы выделить любые представления в вашей UITableViewCell, только когда ячейка не возвращается из dequeueReusableCellWithIdentifier. Выделения - это то, что замедляет прокрутку в табличном представлении, которое должно плавно прокручиваться. Что вам в основном нужно сделать, так это настроить все представления, которые вам понадобятся в ячейке, когда вы не получаете ее при снятии очереди. Когда вы действительно получаете ячейку, находящуюся в очереди, вы должны устанавливать состояние только для какого-либо модельного объекта или чего-то подобного.

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