Xavi Valero
Xavi Valero

Reputation: 2057

Checkbox status changes when uitableview is scrolled up and down

I have a tableview with a lot of entries divided into multiple sections and inside that I have multiple rows.I have a button modelled as a checkbox in each rows. The checkboxes(buttons) can be activated/deactivated when pressed. I am loading an image on the button(checkbox) based on the status, whether it is checked or not. Everything is going fine, until I try to drag my UITableview downwards and then go up, only to find some of my checked checkboxes automatically unchecked. I kind of figured that, this was caused due to the use of

 dequeuereusablecellwithidentifier

I want to avoid this strange behavior of my tableview. Need help in this case.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    UIButton *checkBox = [[UIButton alloc] init];
    checkBox.tag = contact.contactID;
    [cell.contentView addSubview:checkBox];
    [checkBox setFrame:CGRectMake(6,14,20,20)];
    [checkBox release];
}
UIButton *checkBox = (UIButton *)[cell.contentView viewWithTag:contact.contactID];

if(isActivDeactivButton)
{
    [checkBox setImage:[UIImage imageNamed:@"disabled_checkbox.png"] forState:UIControlStateNormal]; 
   }
else{
   [checkBox setImage:[UIImage imageNamed:@"selected_checkbox.png"] forState:UIControlStateNormal];
 }
return cell;
}

Upvotes: 0

Views: 2452

Answers (3)

Xavi Valero
Xavi Valero

Reputation: 2057

I replaced

checkBox.tag = contact.contactID;

with

checkBox.tag = 111;

This solved the problem as my contactID values were changing during scroll.

Upvotes: 0

Dipak Chaudhari
Dipak Chaudhari

Reputation: 655

// Add following methods def in viewController .h 

  -(void)checkButtonPressed:(id)sender;
  -(void)addSelectedCheckBoxTag:(int)value;
  -(void)deleteSelectedCheckBoxTag:(int)value;
  -(BOOL)isSelectedCheckBox:(int)value;

//  add target to the check button in cellForRowAtIndexPath -

    [checkBox addTarget:self action:@selector(checkButtonPressed:) forControlEvents:UIControlStateNormal];

//  Ad following methods in viewController .m where tabelView

  -(void)checkButtonPressed:(id)sender
  {
   UIButton *checkBox=(UIButton*)sender;
   if(checkBox.selected)
    {
     checkBox.selected=false;
     [checkBox setImage:[UIImage imageNamed:@"disabled_checkbox.png"] forState:UIControlStateNormal]; 
     [self deleteSelectedCheckBoxTag:checkBox.tag];
     NSLog(@"unselected ..");
    }
  else
    {
    checkBox.selected=true;
    [self addSelectedCheckBoxTag:checkBox.tag];
    [checkBox setImage:[UIImage imageNamed:@"selected_checkbox.png"] forState:UIControlStateNormal];      
    NSLog(@"selected..");
  }    

 }

   // Add element in to array if already present forget   

  -(void)addSelectedCheckBoxTag:(int)value
     {
      int flag=0;

    for(int i=0;i<[arrayForTag count];i++)
     {        
       if([[arrayForTag objectAtIndex:i] intValue]==value)
       flag=1;
     }
   if(flag==0)
   [arrayForTag addObject:[NSString stringWithFormat:@"%d",value]];
   }

   // delete element add in array if present 

   -(void)deleteSelectedCheckBoxTag:(int)value
    {

   for(int i=0;i<[arrayForTag count];i++)
     {        
      if([[arrayForTag objectAtIndex:i] intValue]==value)
        [arrayForTag removeObjectAtIndex:i];
     }
    }

   // For take is selected or not from array -

-(BOOL)isSelectedCheckBox:(int)value
  {
    for(int i=0;i<[arrayForTag count];i++)
     {        
       if([[arrayForTag objectAtIndex:i] intValue]==value)
         return true;
      }
    return false;
  }

  // In cellForRowAtIndexPath  replace following code 

     if(isActivDeactivButton)
      {
      [checkBox setImage:[UIImage imageNamed:@"disabled_checkbox.png"] forState:UIControlStateNormal]; 
      }
 else{
     [checkBox setImage:[UIImage imageNamed:@"selected_checkbox.png"]  forState:UIControlStateNormal];
   }

    // with following code - 

    if(![self isSelectedCheckBox:checkBox.tag])
     {
       [checkBox setImage:[UIImage imageNamed:@"disabled_checkbox.png"] forState:UIControlStateNormal]; 
     }
    else{
       [checkBox setImage:[UIImage imageNamed:@"selected_checkbox.png"] forState:UIControlStateNormal];
        }

Upvotes: 2

Tim
Tim

Reputation: 14446

Make sure your logic for -tableView:cellForRowAtIndexPath: is set up as follows:

// 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) {
        // this part is called when the cell is created anew
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        // add new components here (this is where you'd add your checkbox control, etc)
    }

    // change the state of components here (this is where you'd make sure your checked property is set correctly

    return cell;
 }

Using dequeueReusableCellWithIdentifier: is great practice for memory management, so you want to keep this for sure.

Upvotes: 2

Related Questions