Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableView repeating cells on scroll

When i scroll my UITableView, for some reason cells seem to be drawn over each other. If i load up my app, a cell will appear something like this:

enter image description here

And upon scrolling this cell off and back on the screen a number of times, it'll start to appear like this:

enter image description here

As you can see, something i can't seem to work out is going wrong. Any ideas?

EDIT: 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:Cell:

//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;
like image 238
Andrew Avatar asked Apr 10 '26 04:04

Andrew


1 Answers

you're just adding more and more UILabels etc to your cell each time it's displayed!

You need to keep track of all the things that you are adding to your cell to make sure that you're only adding them once! There's a couple of ways of doing this but I recommend subclassing UITableViewCell yourself

For example, here's the code to get the createdOnLabel working correctly :

@interface AHTableViewCell : UITAbleViewCell {
    UILabel *createdOnLabel;
}

@end

@implementation AHTableViewCell

@end

Then, your cellForRowAtIndexPath code becomes

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

and your create code becomes :

//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";

so, the first time you create the cell, you create the label. All the other times that you ask the cell to be created, you check to see if the label is already there and if it is, just update it's text.

like image 98
deanWombourne Avatar answered Apr 11 '26 18:04

deanWombourne