Search code examples
iosobjective-cuitableviewuiswitch

Uiswitch in uitableviewcell reset when scroll up or down?


I have a problem with my UISwitch inside a UITableViewCell. When I change the value of one switch then scroll up or down all switches are messed up. I use an array to store state for each switch due to reusability they are still messed up every time.

Here is cellForRowAtIndexPath method:

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

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];


    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                      reuseIdentifier:@"Cell"];

    }

    UISwitch *switchController = [[UISwitch alloc] initWithFrame:CGRectZero];
    CGRect switchFrame = switchController.frame;
   [switchController setOn:YES animated:NO];
    //set its x and y value, this you will have to determine how to space it on the left side
    switchFrame.origin.x = 50.0f;
    switchFrame.origin.y = 10.0f;
    switchController.frame = switchFrame;


    [switchController addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
    [cell addSubview:switchController ];

    UILabel *label ;

    label=(UILabel *)[cell viewWithTag:1];
    NSString *value = [[mainArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
    label.text = value;
    label.textAlignment = NSTextAlignmentRight;
    label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;


    //This for persist switch state when scroll up or down
    if ([[[self.SwitchArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row ]isEqualToString:@"ON"])
    {
       switchController.on=YES;


    }
    else 
    {
       switchController.on=NO;


    }

       return cell;   
}

Here is SwitchChanged event :

-(void)switchChanged:(UISwitch *)sender
{
    UITableViewCell *cell = (UITableViewCell *)[[sender superview] superview];
    NSIndexPath *index=[mainTableView indexPathForCell:cell];

    if (sender.on)
    {

        [[self.SwitchArray objectAtIndex:index.section] replaceObjectAtIndex:index.row withObject:@"ON"];
        NSString *word= [[self.mainArray objectAtIndex:index.section ] objectAtIndex:index.row];

    }
    else
    {
        //call the first array by section
        [[self.SwitchArray objectAtIndex:index.section] replaceObjectAtIndex:index.row withObject:@"OFF"];
         NSString *word= [[self.mainArray objectAtIndex:index.section ] objectAtIndex:index.row];

   }

    [padFactoids setObject:[NSKeyedArchiver archivedDataWithRootObject:SwitchArray] forKey:@"savedArray"];
    [padFactoids synchronize];

}

I will appreciate your help so much.


Solution

  • I am not sure whether this causes your problem, but it will certainly cause other related problems.

    Each time when a cell was moved off screen and a next one appears, the one that just moved off screen will be reused. But you add a new switch object every time to the cell. You are far better off creating those only within the cell==nil block. Give it a tag and use the tag to fetch the object upon reusage as you do with the lable object.