开发者

Content of cellLabel.text seems to be overwriting itself in random cells

开发者 https://www.devze.com 2023-01-15 22:49 出处:网络
I have a UITableView that is being populated from an NSMutable array that has 79 entries in it. When I run my app and scroll down the table there seems to be multiple entries in one cell. It seems to

I have a UITableView that is being populated from an NSMutable array that has 79 entries in it. When I run my app and scroll down the table there seems to be multiple entries in one cell. It seems to happen about a screen height and a half down the table.

For example:

One object in the array is @"Dog" and another is @"Cat". In one cell you can see both Cat and Dog written in the cellLabel text.

Code for init'ing the cells

// Customize the appearance of table view cells.
- (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];
        cell.accessoryType = UITableViewCellAccessoryNone;
    }

    // Configure the cell...

    U开发者_如何学PythonILabel *cellLabel = [[[UILabel alloc] initWithFrame:cell.frame] autorelease];
    cellLabel.text = [symptomsArray objectAtIndex:indexPath.row];
    cellLabel.textColor = [UIColor blackColor];
    cellLabel.backgroundColor = [UIColor clearColor];
    cellLabel.opaque = NO;
    [cell.contentView addSubview:cellLabel];
    cell.contentView.backgroundColor = [UIColor colorWithRed:(214.0/255) green:(215.0/255.0) blue:(217.0/255) alpha:1.0];

    return cell;
}


Keep it Simple.

If you only have a few entries, why not allocate an array of cells before load and load the cell object from the array directly inside:

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

 return [arrayOfCells objectAtIndex:indexPath.row]; //already allocated one single time at the beginning

    }

No more dequeueReusableCellWithIdentifier..

Keep it simple!


Subviews are positioned relative to their superviews' bounds. So, for example, if you want cellLabel to be in the upper-left corner of the content view, you need to set its origin to (0, 0). You're using the cell's frame, which is relative to the upper-left corner of the table view.

When you scroll down, UITableView is reusing old cells, and you're adding additional labels to those cells. These cells have frames with origins offset by a screen or two from the top of the table view, so you're positioning the new labels outside the cell's actual bounds. Here's how to fix it.

static int CellLabelTag = 12345;

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

    UILabel *cellLabel = [[[UILabel alloc] initWithFrame:cell.contentView.bounds] autorelease];
    cellLabel.tag = 585493;
    [cell.contentView addSubview:CellLabelTag];
}

UILabel *cellLabel = (UILabel *)[cell viewWithTag:CellLabelTag];
cellLabel.text = // your text here
// blah blah blah configuration
return cell;


That is because you are adding a label everytime If you really need that new UiLabel then add it inside the if sentence you have and change it's text out of the if

And to do this efficiently you will have to subclass UITableViewCell maybe

Hope this helps


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


Alex answer is the best one here, a lot of people do not realise this is happening, especially if they are not using ClearColor background for the labels, in which case you would never see this overwriting.

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:cell.frame];
        self.cellLabel.textColor = [UIColor blackColor];
        self.cellLabel.backgroundColor = [UIColor clearColor];
        self.cellLabel.opaque = NO;
        [self..contentView addSubview:cellLabel];
        self.contentView.backgroundColor = [UIColor colorWithRed:(214.0/255) green:(215.0/255.0) blue:(217.0/255) alpha:1.0];
    }

    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 = [symptomsArray objectAtIndex:indexPath.row];

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消