AsTheWormTurns
AsTheWormTurns

Reputation: 1316

UITableView, icons duplicated after scrolling

I'm using the following code to show a particular UITableView: the first row must show an icon, all the "inner" rows a different one and, at the end, there's another icon. So, we have three icons, one for the top cell, one for the "inner" cells, and one for the bottom cell.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"cell"];

    if (cell == nil) 
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]autorelease];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;   
    }

    TabBarTestAppDelegate *delegate = (TabBarTestAppDelegate *)[[UIApplication sharedApplication] delegate];
    NSArray *local = delegate.myData;
    // ok, it's horrible, don't look at it   :-)
    cell.textLabel.text = [NSString stringWithFormat:@"%@%@", @"       " ,[local objectAtIndex:indexPath.row]];
    //
    NSString* name;
    if (indexPath.row == 0) {
        name = @"topicon";
    }
    else if (indexPath.row + 1 == [local count]) {
        name = @"bottomicon";
    }
    else {
        name = @"innericon";
    }
    //
    UIImage *leftIcon = [[UIImage alloc] initWithContentsOfFile: [[NSBundle mainBundle] pathForResource:name ofType:@"png"]];
    //
    UIImageView *imageView = [[UIImageView alloc] initWithImage:leftIcon];
    [cell addSubview:imageView];
    imageView.frame = CGRectMake(20,0,30,44);
    [leftIcon release];
    [imageView release[;

    return cell;
}

What happens. The first time the UITableView is loaded by the simulator there's apparently no problem, but, after scrolling, it happens something strange: the first and the last cell show the right icon AND, underneath, another icon. The icon under the bottom and the top icon is an "inner" icon, that should appear only when indexPath.row!=0 or indexPath.row+1!=[local count]. Frankly, I don't know if every other icon gets duplicated while scrolling, but this effect is quite visible.

I imagined there could be some issue with the subview, but, being an objective-C newbie, I can't imagine exactly what.

Any help is appreciated.

Upvotes: 2

Views: 2866

Answers (4)

rckoenes
rckoenes

Reputation: 69479

Well the TableView is reusing the cells, and you add the image every time a cell is displayed.

Thus when reusing the cell you add an other image, but there already is an image.

You will have to reuse the image view, and only add the image if you create the cell.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *cellIdentifer = @"cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifer];

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


        UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(20,0,30,44)];
        imageView.tag = 1001;
        [cell addSubview:imageView];
        [imageView release], imageView= nil;
    }

    TabBarTestAppDelegate *delegate = (TabBarTestAppDelegate *)[[UIApplication sharedApplication] delegate];
    NSArray *local = delegate.myData;
    // ok, it's horrible, don't look at it   :-)
    cell.textLabel.text = [NSString stringWithFormat:@"%@%@", @"       " ,[local objectAtIndex:indexPath.row]];
    //

    NSString* name = nil;;
    if (indexPath.row == 0) {
        name = @"topicon";
    }
    else if (indexPath.row + 1 == [local count]) {
        name = @"bottomicon";
    }
    else {
        name = @"innericon";
    }

    UIImageView *imageView = (UIImageView *)[cell viewWithTag:1001];
    imageView.image = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:name ofType:@"png"]];

    return cell;
 }

Upvotes: 3

Luca Savarese
Luca Savarese

Reputation: 1

Had a similar problem. I needed to add an image to the last cell of my table, the one with indexPath.row set to 15.

So i used the trick shown above by Glenn (tnx a lot!), ending up with something like this:

NSString *CellIdentifier = @"Cell";
if (indexPath.row==15)
    CellIdentifier=@"CamCell";
NuovaSegnalazioneCell *cell = (NuovaSegnalazioneCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
    cell = [[NuovaSegnalazioneCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
    cell.detailTextField.delegate = self;
    NSLog(@"INIT CELL %d",indexPath.row);
}

This way the 15th cell has a different CellIdentifier and it isn't re-used anywhere else while scrolling the table.

Upvotes: 0

Glenn Reid
Glenn Reid

Reputation: 121

I am adding a solution to this because I've been beating my head against this for a little while, and most of the answers here are 2-3 years old, and there's a much better way now to solve this...

In the Storyboard editor, you can drag more than one prototype cell into your UITableView, and give them different reuse Identifiers, ike this:

enter image description here

if ( specialCase ) {
    UIColor *color = [UIColor colorWithRed:0.2 green:(0.8) blue:0.2 alpha:1.0];
    cell = [tableView dequeueReusableCellWithIdentifier:@"TopCellGreen" forIndexPath:indexPath];
    cell.textColor = color;
} else {
    cell = [tableView dequeueReusableCellWithIdentifier:@"TopCell"  forIndexPath:indexPath];
}

Note the different identifiers. This will prevent your customizations (green text) from showing up randomly in other cells that [re]use the same cell.

Upvotes: 0

Ilanchezhian
Ilanchezhian

Reputation: 17478

One thing. Don't add new imageviews again and again. Try to reuse them. I have given a simple example for reusing components inside a cell , in my post here.

Upvotes: 1

Related Questions