Question

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.

Was it helpful?

Solution

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;
}

OTHER TIPS

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 !!

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

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top