3

I have used Cell.ContentView in my implementation for customizing the cell contents. It works fine but the only problem is when I have many cells and I scroll them up and down, the cell contents gets overwritten into the cells just become hidden followed by visible. Suppose I scroll first cell up and then again takes it down, the last cell's contents gets overwritten on first cell!!

I debugged enough on this but couldn't find the exact solution. I tried checking Cell.ContentView.SubViews count and if it 0 then only add other subviews. This doesn't display any cell contents until I scroll them up and down but once contents appeared, it doesn't overwrite..Little bit strange..!! I also made sure that I am using reusing the cell correctly. Following is my code that adds subviews into cell's contentview. Please let me know how could I get rid of this issue.

P.S: Don't worry about the variables and calculations I have done. Assume that it returns correct values. :)

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

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

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

    NSInteger totalAvailableSpace = IPHONE_DISPLAY_WIDTH - iconSize - accesorySize - 10;
    NSInteger lableHeight = [[cellDetails objectForKey:@"TableItemTextFontSize"] intValue] * 2 + 10;

    UILabel *textLabel = nil;
    textLabel = [[[UILabel alloc] initWithFrame:CGRectMake(iconSize+12, self.tableCellHeight/2 - lableHeight/2, totalAvailableSpace * 0.8, lableHeight)] autorelease];
    textLabel.numberOfLines = 2;
    textLabel.lineBreakMode = UILineBreakModeWordWrap;
    textLabel.textAlignment = UITextAlignmentLeft;
    textLabel.text = [cellDetails objectForKey:@"TableItemMainText"];
    if ([textLableColor scanHexInt:&hex]) {
        textLabel.textColor = UIColorFromRGB(hex);
    }
    textLabel.font = [UIFont fontWithName:[cellDetails objectForKey:@"TableItemTextFontName"] size:[[cellDetails objectForKey:@"TableItemTextFontSize"] intValue]]; 
    [cell.contentView addSubview:textLabel];
    textLabel.backgroundColor = [UIColor clearColor];

    lableHeight = [[cellDetails objectForKey:@"TableItemDetailTextFontSize"] intValue] * 2 + 10;
    UILabel *detailTextLabel = nil;
    detailTextLabel = [[[UILabel alloc] initWithFrame:CGRectMake(iconSize+10+totalAvailableSpace * 0.8+5, self.tableCellHeight/2 - lableHeight/2, totalAvailableSpace * 0.2 - 10, lableHeight)] autorelease];
    detailTextLabel.numberOfLines = 2;
    detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
    detailTextLabel.textAlignment = UITextAlignmentLeft;
    detailTextLabel.text = [cellDetails objectForKey:@"TableItemDetailText"];
    if ([detailTextLableColor scanHexInt:&hex]) {
        detailTextLabel.textColor = UIColorFromRGB(hex);
    }
    detailTextLabel.font = [UIFont fontWithName:[cellDetails objectForKey:@"TableItemDetailTextFontName"] size:[[cellDetails objectForKey:@"TableItemDetailTextFontSize"] intValue]];
    [cell.contentView addSubview:detailTextLabel];
    detailTextLabel.backgroundColor = [UIColor clearColor];

    return cell;
}

Thanks.

Paresh Masani
  • 7,474
  • 12
  • 73
  • 139
  • Based on [this](http://stackoverflow.com/questions/2027455/repeat-problem-of-tableview-cell-during-scrolling-in-iphone), removing cell===nil condition seems to be working but not a ideal solution! – Paresh Masani Jun 16 '11 at 11:13

5 Answers5

6

That is because toy are adding the views to your cell over and over again.

You should only add them when you create the cell and just set the labels when the cell is being reused.

You could set tags for your label, so that you can set it texts afterwards. The code bellow does the trick

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

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        if(style == UITableViewCellStyleValue1)
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        else
            cell = [[[UITableViewCell alloc] initWithStyle:style reuseIdentifier:CellIdentifier] autorelease];


        NSInteger totalAvailableSpace = IPHONE_DISPLAY_WIDTH - iconSize - accesorySize - 10;
        NSInteger lableHeight = [[cellDetails objectForKey:@"TableItemTextFontSize"] intValue] * 2 + 10;

        UILabel *textLabel = nil;
        textLabel.tag = 1;
        textLabel = [[[UILabel alloc] initWithFrame:CGRectMake(iconSize+12, self.tableCellHeight/2 - lableHeight/2, totalAvailableSpace * 0.8, lableHeight)] autorelease];
        textLabel.numberOfLines = 2;
        textLabel.lineBreakMode = UILineBreakModeWordWrap;
        textLabel.textAlignment = UITextAlignmentLeft;
        textLabel.text = [cellDetails objectForKey:@"TableItemMainText"];
        if ([textLableColor scanHexInt:&hex]) {
            textLabel.textColor = UIColorFromRGB(hex);
        }
        textLabel.font = [UIFont fontWithName:[cellDetails objectForKey:@"TableItemTextFontName"] size:[[cellDetails objectForKey:@"TableItemTextFontSize"] intValue]]; 
        [cell.contentView addSubview:textLabel];
        textLabel.backgroundColor = [UIColor clearColor];

        lableHeight = [[cellDetails objectForKey:@"TableItemDetailTextFontSize"] intValue] * 2 + 10;
        UILabel *detailTextLabel = nil;
        detailTextLabel.tag = 2;
        detailTextLabel = [[[UILabel alloc] initWithFrame:CGRectMake(iconSize+10+totalAvailableSpace * 0.8+5, self.tableCellHeight/2 - lableHeight/2, totalAvailableSpace * 0.2 - 10, lableHeight)] autorelease];
        detailTextLabel.numberOfLines = 2;
        detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
        detailTextLabel.textAlignment = UITextAlignmentLeft;
        detailTextLabel.text = [cellDetails objectForKey:@"TableItemDetailText"];
        if ([detailTextLableColor scanHexInt:&hex]) {
            detailTextLabel.textColor = UIColorFromRGB(hex);
        }
        detailTextLabel.font = [UIFont fontWithName:[cellDetails objectForKey:@"TableItemDetailTextFontName"] size:[[cellDetails objectForKey:@"TableItemDetailTextFontSize"] intValue]];
        [cell.contentView addSubview:detailTextLabel];
        detailTextLabel.backgroundColor = [UIColor clearColor];

    } else {

        UILabel *textLabel = (UILabel *)[cell viewWithTag:1];
        textLabel.text = [cellDetails objectForKey:@"TableItemMainText"];

        UILabel *detailTextLabel = (UILabel *)[cell viewWithTag:2];
        detailTextLabel.text = [cellDetails objectForKey:@"TableItemDetailText"];

    }

    return cell;
}
Felipe Sabino
  • 17,825
  • 6
  • 78
  • 112
  • Hmmm...that's great way to do it. Thank you very much! – Paresh Masani Jun 16 '11 at 11:15
  • Yes, that is the whole purpose of reusing the cell object :) – Felipe Sabino Jun 16 '11 at 11:16
  • You should remove the "else", you're not adding any text to the labels when they're being just created. – pablasso Nov 09 '11 at 18:56
  • sorry @pablasso , I didn't get it... The last else is the one that updates the cell label text when the delegate methods is called and I am able to reuse a cell instance. Is this the one u are referring to? – Felipe Sabino Nov 10 '11 at 11:31
  • Yeah that one, if you only set the text when the cell isn't nil, you'll end up with a blank cell on the first run. You want to set the text every time, regardless of the cell being reused or not. – pablasso Nov 10 '11 at 15:13
  • hmmm... if you should look at the code again with more attention you will see that it is setting both labels `text` property both inside the `if` and `else` block... pay attention where it calls `cellDetails objectForKey:` :) – Felipe Sabino Nov 10 '11 at 21:47
4
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];

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

Make sure that dequeueReusableCellWithIdentifier and reuseIdentifier should be nil

Now it will work !!

j0k
  • 22,600
  • 28
  • 79
  • 90
yoga
  • 51
  • 1
  • 3
  • This isnt exactly the right way to do it. You are not using reusable cells to create the table. you are creating cells everytime they are about to show up on the screen when scrolling. – Rashid Sep 15 '14 at 12:18
2

Place all the cell UI content inside if(cell==nil){uilabel,uilabel or anythingUI related} ...since ui should be call only once at time of creating cel

2

To be clear, your problem is that as you scroll a cell into view you will often wind up with the text of the new cell being written over the top of a cell that was just scrolled offscreen?

The problem is that dequeueReusableCellWithIdentifier: doesn't "clean up" the cell (it calls prepareForReuse, but that's it), so all your old subviews are still in place. If you are going to reuse cells, you shouldn't be recreating these subviews each time. Instead, just adjust the properties of the existing subviews on a cell you get back from dequeueReusableCellWithIdentifier:, and only create the new subviews on a newly-allocated cell. Subclassing UITableViewCell can help with this, both to provide properties/ivars in which to hold references to these subviews and to organize the code a little nicer by moving the creation of subviews and the updating into appropriate methods. Or you could just not reuse cells, by passing nil for the reuse identifier.

The most likely reason that it didn't display any content until you scroll up and down is that a newly-created cell may have the framework-provided text field and image view, which may then be removed if the framework determines that you aren't actually using them.

Anomie
  • 92,546
  • 13
  • 126
  • 145
0

In iOS5 UILineBreakModeWordWrap is deprecated. You should use NSLineBreakByWordWrapping instead.

This would change you code to look like detailTextLabel.lineBreakMode = NSLineBreakByWordWrapping and textLabel.lineBreakMode = NSLineBreakByWordWrapping.

David.Jones
  • 1,413
  • 8
  • 16