0

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];

}
marko
  • 9,029
  • 4
  • 30
  • 46

3 Answers3

3

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.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • THANK you for your quick reply this means a lot .. But could you please give me a details of how to solve point#2 ? I will appreciate it SO MUCH YOU WILL BE A LIFE SAVER – Alanoud Aldrees Apr 25 '13 at 20:04
  • You are already testing for whether this is "virgin" cell with `if (cell == nil)`. That condition is also where you need to add the switch. That way, if the cell is *not* nil, you know for sure that it has a switch. – matt Apr 25 '13 at 20:13
  • It might help you to read my book chapter on this topic: http://www.apeth.com/iOSBook/ch21.html#_table_view_cells – matt Apr 25 '13 at 20:16
  • thank you matt . But i tried to put my code in the first if (cell == nil ) and it does not work :( – Alanoud Aldrees Apr 25 '13 at 21:29
  • I do not say that everything you want to have happen will happen just because you do what I said. But I do say that what you were doing was wrong in the way I described. – matt Apr 25 '13 at 23:37
0

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];
}
Jeffery Thomas
  • 42,202
  • 8
  • 92
  • 117
0

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;
maroux
  • 3,764
  • 3
  • 23
  • 32
  • I would strongly discourage `switchController.tag = 'swch'`. see: http://stackoverflow.com/questions/7755202/multi-character-constant-warnings – Jeffery Thomas Apr 26 '13 at 14:51
  • @JefferyThomas Good to know. Although, help me understand why this is a bad idea in this particular instance? I don't see any portability concern here. – maroux Apr 26 '13 at 14:55
  • int x = 'xxxx' is undefined behavior in Standard C (GCC and LLVM have implementation defined behavior for it). The real problem I have with it is that is obscures the meaning of tag. Tag is a number not a 4 character sequence. – Jeffery Thomas Apr 26 '13 at 15:23
  • In context of iOS app built using gcc/llvm, we should be okay :) Tags are in general very bad since they don't have semantics, there are possibilities of clashes and maintenance is a headache. I like 4 char codes because they are a good way to reduce some of those problems. I would say `swch` has more meaning then `1`, don't you agree? An enum that defines all tags is the best solution. – maroux Apr 26 '13 at 15:29