UIswitch in a table cell reused

2020-05-03 11:53发布

问题:

I have a problem with uiswitch in my UITableViewCell that whenever i change a switch value in a specific cell that belongs to a specific section. All other sections cells that have same inexPath.row change . Please help ?

Here is my code of cellForRowAtIndexPath method:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    //UISwitch *switchview = nil ;

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



    }


    UISwitch *switchController = [[UISwitch alloc] initWithFrame:CGRectZero];
    CGRect switchFrame = switchController.frame;
    NSString *str = [[self.SwitchArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
    NSLog(@"string in cell%@", str);


    //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 ];
    [addSubview:switchController];


    if ([[[self.SwitchArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row ]isEqualToString:@"ON"])
 {
        switchController.on=YES;
 }
    else
    {
        switchController.on=NO;
    }


    return cell;

}

And here is SwitchChangedEvent:

-(void)switchChanged:(UISwitch *)sender
{
    UITableViewCell *cell = (UITableViewCell *)[sender 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];

}

回答1:

You have two main problems:

  1. This code is wrong:

      [cell addSubview:switchController ];
    

    Never add a subview to the cell; add it only to the cell's contentView.

  2. You are adding the switch every time through cellForRowAtIndexPath:. But these cells are being reused. So some cells already have the switch. Thus you are adding many switches to some cells.



回答2:

As already pointed out by others, you're adding multiple switches to each cell. FTFY:

UISwitch *switchController = nil;
if (cell == nil)
{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                  reuseIdentifier:CellIdentifier];
    switchController = [[UISwitch alloc] initWithFrame:CGRectZero];
    switchController.tag = 'swch';
    CGRect switchFrame = switchController.frame;
    //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.contentView addSubview:switchController];
}
else 
{
    switchController = (UISwitch*)[cell.contentView viewWithTag: 'swch'];
    NSAssert(switchController != nil, @"how?");
}

NSString *str = [[self.SwitchArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
NSLog(@"string in cell%@", str);

switchController.on = [str isEqualToString:@"ON"];

return cell;


回答3:

If you look, I think you will find that you are building up multiple switches and on each cell.

As cells get reused, you add a new switch but do not remove the old one. I think this my be at least part of the cause of your problem.


UPDATE

I think I would handle this a bit differently than others. I think it will be easier for @AlanoudAldrees to remove the old switch.

if (cell == nil)
{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                  reuseIdentifier:CellIdentifier];
}
else
{
    for (UIView *view in cell.subviews)
        if ([view isKindOfClass:[UISwitch class]])
            [view removeFromSuperview];
}