【问题标题】:Uiswitch in uitableviewcell reset when scroll up or down?向上或向下滚动时,uitableviewcell中的uiswitch会重置吗?
【发布时间】:2013-04-26 14:09:34
【问题描述】:

我在UITableViewCell 中的UISwitch 有问题。当我更改一个开关的值时,向上或向下滚动所有开关都搞砸了。由于可重用性,我使用一个数组来存储每个开关的状态,但每次它们仍然搞砸了。

这里是cellForRowAtIndexPath方法:

- (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;   
}

这里是 SwitchChanged 事件:

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

}

非常感谢您的帮助。

【问题讨论】:

  • 尝试设置断点并查看self.SwitchArray 以确保它存在(不是nil)并包含您期望的数据。我猜你的数组是nil,所以你的返回开关一直处于关闭状态。
  • @DBD 比你的回应。但我的意思并不是所有的开关都关闭了。我的意思是,每当我更改表格视图上的一个开关然后向上或向下滚动时,它们就会变得一团糟,关闭的开关打开,反之亦然。
  • 正如 ChrisH 所提到的,每次配置单元时,您都会创建一个新的UISwitch,即使开关已经存在。这是您必须解决的问题,但我仍然认为您需要检查数据模型,因为我不相信您的价值观会像您认为的那样保存在其中。

标签: ios objective-c uitableview uiswitch


【解决方案1】:

在你的头文件中声明一个 NSMutableArray,我们把它命名为 switchStates

在您的viewDidLoad中,根据开关的数量分配内存并添加字符串“OFF”的对象:

switchStates = [[NSMutableArray alloc] init];
for (int i; i <= switchesArray.count; i++) {
    [switchStates addObject:@"OFF"];
}

在触发开关时运行的方法中:

NSString *theSwitchPosition = [NSString stringWithFormat:@"%@", switchControl.on ? @"ON" : @"OFF"];
[switchStates replaceObjectAtIndex:aPath.row withObject:theSwitchPosition];

之后,在您创建开关的方法中:

if ([[switchStates objectAtIndex:indexPath.row] isEqualToString:@"ON"]) {
    mySwitch.on = YES;
} else {
    mySwitch.on = NO;
}

这对我有用,祝你好运..

【讨论】:

    【解决方案2】:

    我不确定这是否会导致您的问题,但肯定会导致其他相关问题。

    每次将一个单元格移出屏幕并出现下一个时,刚刚移出屏幕的单元格将被重复使用。 但是您每次都向单元格添加一个新的开关对象。最好只在 cell==nil 块内创建它们。给它一个标签并使用标签在重用时获取对象,就像使用标签对象一样。

    【讨论】:

    • 谢谢,这很有帮助。但是现在一个新问题是我的表有很多部分,并且当第 0 行第 0 行更改切换时,我的表有很多行,然后所有部分中的所有第 0 行都更改了?你知道为什么会这样吗?
    【解决方案3】:

    每次 tableView 请求一个单元格时,您都会创建一个新开关。您只想为每个单元格创建一次开关:

    UISwitch *switchController;
    
     if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                      reuseIdentifier:@"Cell"];
    
        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.contentView addSubview:switchController ];
    
        switchController.tag = 123; //Arbitrary number...can be anything 
    }
    else {
        switchController = (UISwitch *)[cell.contentView viewWithTag:123];
    }
    
    //Now set the switch state according to your data model array
    

    将子视图添加到单元格的 contentView 而不是单元格本身通常也是一种更好的做法。

    【讨论】:

    • 能否请您详细说明如何操作?这对我有很大帮助。谢谢
    • 好建议。分配新开关时有一个“=”太多。并且调用[switchController setOn:YES animated:NO]; 没有任何意义,因为值是稍后设置的。
    • @HermannKlecker 是的,= = 是我的错字。 [switchController setOn:YES animated:NO]; 你说的对
    • 很高兴为您提供帮助...您可以通过将您的问题标记为已回答并支持我们的回复来回报您的青睐!
    • @user2323070 似乎您没有跟踪某些数组/字典中开关的变化,不是吗? ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多