Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop UITableView cell is overwriting the contents?

I am using a UITableView and I'm noticing that the cells in my tableview are getting progresively bolder as I scroll, it is overwriting the contents and I want to stop this but can't see where I'm going wrong.

On my UITableView, for some reason when I scroll the contents of the tableview get messed up with the the manually created UILabel.

I require a manual UILabel because I need to have custom cells later on.

As I scroll up and down, the labels get progressively bolder and bolder; they always overlap and sometimes even affects rows lower down (even before they are in the viewport).

If I keep doing it, the cell contents become unintelligable.

This only happens if there the backgroundColor is not set as clearColor.

I have attempted [cellLabel setClearsContextBeforeDrawing:YES]; and [self.tableView setClearsContextBeforeDrawing:YES]; to no effect.

If I use cell.textLabel.text then the problem seems to go away.

Code and an image sample follows.

  // Simple table view
    - (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    {
        static NSString *CellIdentifier = @"Cell";

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

        // Configure the cell...
        //[self configureCell:cell atIndexPath:indexPath];


        NSString *txt = @"Product";


        //cell.textLabel.text = txt;
        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        UIView *cellView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, cell.frame.size.height)];

        UILabel *cellLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 120, 35)];
        [cellLabel setText:txt];
        [cellLabel setFont:[UIFont boldSystemFontOfSize:12]];
        [cellLabel setBackgroundColor:[UIColor clearColor]];

        [cellView addSubview:cellLabel];
        [cellLabel release];
        [cell.contentView addSubview:cellView];
        [cellView release];


        return cell;
    }


Image follows;


![image of uitableview][1]


  [1]: http://i.stack.imgur.com/5lNy6.png


// Edit to include context

I am using a dictionary to display the contents of the UITableViewCells.

I have attempted to do the following;

    - (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    {
        static NSString *CellIdentifier = @"Cell";

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

            [self configureCell:cell atIndexPath:indexPath];
        } // end if


        // Configure the cell...
        //
       // Moved to inside the cell==nil        

        return cell;
    }

-(void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{

    // Get the txt from the Dictionary/Plist... *removed due verboseness*

    UILabel *cellLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 120, 35)];
    [cellLabel setText:txt];
    [cellLabel setFont:[UIFont boldSystemFontOfSize:12]];
    [cellLabel setBackgroundColor:[UIColor clearColor]];

    [cell.contentView addSubview:cellLabel];
    [cellLabel release];
}

This, although it fixes the problem of overwriting -- it causes a problem -- it makes labels repeatedly appear in totally random places -- the following is just an example, other fields and labels also repeat.

See picture below;

repeating labels in uitableview

like image 545
zardon Avatar asked Mar 20 '12 20:03

zardon


3 Answers

    // cell reuse
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

returned you the cell already been used, it already has an UILabel subview and you are adding another over it. Put the adding subviews at the section

   if (cell == nil) { //cell initialization

and edit the subviews as needed after the cell initialization, you can access them by tag for example.

like image 144
A-Live Avatar answered Oct 17 '22 15:10

A-Live


You are adding the label to the same reused cell every time, that is why it is getting bolder. When you use dequeueReusableCellWithIdentifier, you are grabbing a cell that has already been displayed on the screen, which is the correct thing to do, but you have already put a label on it. As the label will be in the same position relative to the cell each time, and the same color etc.. (the only dynamic element will be the text), you should set all this up only once.

My preferred solution is to create a custom cell with the properties that you want. So in this case, you would create

@interfacce MyCustomCell : UITableViewCell
    @property (nonatomic) UILabel *cellLabel;
@end

Give it a property UILabel *cellLabel, and do all the code you have above apart from setting the labels text in the init of MyCustomCell.m, replace any instances of cell with self, for example:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

    if (self)
    {
        self.cellLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 120, 35)];
        [self.cellLabel setText:txt];
        [self.cellLabel setFont:[UIFont boldSystemFontOfSize:12]];
        [self.cellLabel setBackgroundColor:[UIColor clearColor]];
    }

    return self;
}

Now in your cellForRowAtIndexPath use MyCustomCell, where you check if cell == nil, you might want to also check the cell label:

if(cell == nil || cell.cellLabel == nil)

Initialise it in exactly the same way:

cell = [[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

now, all you need to do is set:

cell.cellLabel.text = ....;

your code in cellForRowAtIndexPath is a lot cleaner, memory efficient and and you will not get your bug.

Remember to set your cell to be of type MyCustomCell in interface builder.

like image 6
felbus Avatar answered Oct 17 '22 16:10

felbus


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

           UITableViewCell *cell = (UITableViewCell*)[self.YourTableName dequeueReusableCellWithIdentifier:nil];        
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
        }


            return cell; 
        }

use ReusablecellIdentifier nil so it working correctly.....

like image 4
jayesh kavathiya Avatar answered Oct 17 '22 15:10

jayesh kavathiya