user4487951
user4487951

Reputation:

Having problems with the method: prepareForReuse

I have a custom UITableViewCell, and when it's selected, it expands and adds a UILabel to the selected cells UIView that I added in the storyBoard.

When I run the app and select a cell, the label gets added to myView as expected. The problem is, when I scroll down, the label is also shown at another cell.

Apparently the reason its behaving like so, is because I'm reusing the cell and I don't clean them as Emilie stated. I'm trying to call the method of prepareForReuse and 'cleaning' the cell, but I'm having trouble doing that. Here is my code:

- (void)prepareForReuse {
    NSArray *viewsToRemove = [self.view subviews];
    for (UILablel *v in viewsToRemove) {
    [v removeFromSuperview];
}

Doing that, cleans even the selected cells label.

- (void)viewDidLoad {
    self.sortedDictionary = [[NSArray alloc] initWithObjects:@"Californa", @"Alabama", @"Chicago", @"Texas", @"Colorado", @"New York", @"Philly", @"Utah", @"Nevadah", @"Oregon", @"Pensilvainia", @"South Dekoda", @"North Dekoda", @"Iowa", @"Misouri", @"New Mexico", @"Arizona", @"etc", nil];

    self.rowSelection = -1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CategorieCell *customCell = [tableView dequeueReusableCellWithIdentifier:@"cellID" forIndexPath:indexPath];
    customCell.title.text = [self.sortedDictionary objectAtIndex:indexPath.row];
    return customCell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    CategorieCell *customCell = (CategorieCell *)[tableView cellForRowAtIndexPath:indexPath];

    if (self.info) {
        [self.info removeFromSuperview];
    }

    self.info = [[UILabel alloc] init];
    [self.info setText:@"Hello"];
    [self.info setBackgroundColor:[UIColor brownColor]];

    CGRect labelFrame = CGRectMake(0, 0, 50, 100);
    [self.info setFrame:labelFrame];

    [customCell.infoView addSubview:self.info];

    NSLog(@"%ld", (long)indexPath.row);

    self.rowSelection = [indexPath row];
    [tableView beginUpdates];
    [tableView endUpdates];

}


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([indexPath row] == self.rowSelection) {
        return 159;
    }
    return 59;
}

Upvotes: 0

Views: 692

Answers (1)

Emilie
Emilie

Reputation: 2413

The answer is quite simple : you reuse your cell like you should, but never clean them

Reusing your UITableViewCell means that the cell you clicked on previously will be reused when it will go off-screen.

When clicked, you add a view to your UITableViewCell. When reused, the view is still there because you never remove it.

You have two choices : One, you could set a tag of the self.info view (or check with the indexpath you're keeping in memory), then check when you dequeue the cell if the info view is there, and remove it. The cleaner solution would be to implement the view removal by overriding the prepareForReuse method of your custom UITableViewCell

Precision

The first thing you need to do is set a tag for your self.info view after initializing it:

[self.info setTag:2222];

If you want to keep it as simple as possible, you could check and remove the self.info view directly in your cellForRowAtIndexPath method :

CategorieCell *customCell = [tableView dequeueReusableCellWithIdentifier:@"cellID" forIndexPath:indexPath];
customCell.title.text = [self.sortedDictionary objectAtIndex:indexPath.row];
if [customCell.infoView viewWithTag: 2222] != nil {
    [self.info removeFromSuperview]
} 
return customCell;

I am not a percent sure this code compiles, I cannot test it on my side for now. Hope it works !

Upvotes: 1

Related Questions