滚动 UITableView 时单选按钮未选中

Posted

技术标签:

【中文标题】滚动 UITableView 时单选按钮未选中【英文标题】:Radio buttons get unselected while scrolling UITableView 【发布时间】:2015-08-05 07:30:19 【问题描述】:

我在 UITableView Cell 上有两个单选按钮。我可以在向下滚动 UITableView 时选择其中一个,但是当我向上滚动 tableview 时,所有单选按钮都会被取消选中。滚动后,我也想让它们保持选中状态,但我无法做到这一点......所以请任何有解决方案的人帮助我。谢谢

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

    static NSString *cellIdentifier = @"cell";
    customCell *cell = (customCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil)
    
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"customCell" owner:self options:nil];
        cell = [nib objectAtIndex:0];

    

    leftBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
    leftBtnclick.tag=999;
    [leftBtnclick setImage:[UIImage imageNamed:@"unchecked.png"] forState:UIControlStateNormal];
    [leftBtnclick setImage:[UIImage imageNamed:@"checked.png"] forState:UIControlStateSelected];

    if (screenHeight == 667)
    
        [leftBtnclick setFrame:CGRectMake(50, 59, 30, 30)];
     
    else if(screenHeight == 480)
    
        [leftBtnclick setFrame:CGRectMake(50, 40, 30, 30)];

    

    [leftBtnclick addTarget:self action:@selector(leftTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
    [cell.leftOptBtn addTarget:self action:@selector(leftTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
    [cell.contentView addSubview:leftBtnclick];

    rightBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
    rightBtnclick.tag=1000;
    [rightBtnclick setImage:[UIImage imageNamed:@"unchecked.png"] forState:UIControlStateNormal];
    [rightBtnclick setImage:[UIImage imageNamed:@"checked.png"] forState:UIControlStateSelected];

    if (screenHeight == 667)
    
       [rightBtnclick setFrame:CGRectMake(180, 59, 30, 30)];
    
    else if(screenHeight == 480)
    
        [leftBtnclick setFrame:CGRectMake(50, 40, 30, 30)];

    

    [rightBtnclick setFrame:CGRectMake(180, 59, 30, 30)];
    [rightBtnclick addTarget:self action:@selector(rightTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
    [cell.rightOptBtn addTarget:self action:@selector(rightTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
    [cell.contentView addSubview:rightBtnclick];

    cell.numberLbl.text = [numberArray objectAtIndex:indexPath.row];
    cell.questionLbl.text = [questionArray objectAtIndex:indexPath.row];
    [cell.leftOptBtn setTitle:[leftOptionArray objectAtIndex:indexPath.row] forState:UIControlStateNormal];
    [cell.rightOptBtn setTitle:[rightOptionArray objectAtIndex:indexPath.row] forState:UIControlStateNormal];
    return cell;


-(void)leftTickBtnClicked:(id)sender

    UIButton *leftTickBtn=(UIButton *)sender;
    leftTickBtn.selected=!leftTickBtn.selected;
    for(UIView *vw in [[sender superview]subviews])
    
        if([vw isKindOfClass:[UIButton class]] && vw.tag==1000)
        
            UIButton *rightTickBtn=(UIButton *)vw;

            if(leftTickBtn.selected)
            
                rightTickBtn.selected=NO;
            
            else
            
                rightTickBtn.selected=YES;
            

        
    



-(void)rightTickBtnClicked:(id)sender


    UIButton *rightTickBtn=(UIButton *)sender;
    rightTickBtn.selected=!rightTickBtn.selected;


    for(UIView *vw in [[sender superview]subviews])
    
        if([vw isKindOfClass:[UIButton class]] && vw.tag==999)
        
            UIButton *leftTickBtn=(UIButton *)vw;

            if(rightTickBtn.selected)
            
                leftTickBtn.selected=NO;
            
            else
            
                leftTickBtn.selected=YES;
            

        
    



【问题讨论】:

这个问题有时会因重用 tableviewcell 而出现。删除if 语句并将NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"customCell" owner:self options:nil]; cell = [nib objectAtIndex:0];if 中写入这些行,然后重试。 还是不行......@SweetAngel 您的 tableview 中有多少行? 16 行 ...@SweetAngel 【参考方案1】:

您只创建了一个leftTickBtnrightTickBtn,并在每次创建行时对其进行更新。所以最后不管你用单选按钮做了什么,它只影响到最后一个按钮。

更新您的代码如下:

UIButton *leftBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
leftBtnclick.tag=999+indexPath.row;

UIButton *rightBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
rightBtnclick.tag=1000+indexPath.row;

并实现如下方法:

- (IBAction)leftTickBtnClicked:(UIButton *)sender

    sender.selected = TRUE;
    UITableViewCell *cell = [tblAppointment cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1000-sender.tag inSection:0]];

    for (id view in cell.contentView.subviews)
    
        if ([view isKindOfClass:[UIButton class]])
        
            // your code
             UIButton *btnRight = (UIButton *)view;
             if (sender.selected == TRUE)
                 btnRight.selected = FALSE;
             else
                 btnRight.selected = TRUE;
        
    

- (IBAction)rightTickBtnClicked:(UIButton *)sender

    sender.selected = TRUE;
    UITableViewCell *cell = [tblAppointment cellForRowAtIndexPath:[NSIndexPath indexPathForRow:999-sender.tag inSection:0]];

    for (id view in cell.contentView.subviews)
    
        if ([view isKindOfClass:[UIButton class]])
        
            // your code
             UIButton *btnLeft = (UIButton *)view;
             if (sender.selected == TRUE)
                 btnLeft.selected = FALSE;
             else
                 btnLeft.selected = TRUE;
        
    

【讨论】:

感谢您的宝贵时间,但它对我不起作用...遇到同样的问题【参考方案2】:

由于可重复使用单元的工作方式,您遇到了这个问题。 当您滚动离开您在单选按钮上进行更改的单元格,然后尝试滚动回该特定行时,可重复使用的单元格dequeueReusableCellWithIdentifier 并不能保证它将出列您所做更改的完全相同的单元格,并且很可能它将使您未进行任何更改的单元格出列

您需要跟踪cellForRowAtIndexPath 之外的列表中的按钮选择,并将选择重新分配给cellForRowAtIndexPath 中的单选按钮,这与每次使用cell.numberLbl.text = [numberArray objectAtIndex:indexPath.row]; 分配单元格文本的想法相同,方法是使用数组中的 indexPath.row

请参阅下面代码的修改 [1] 、 [2] 和 [3] (尚未测试但您明白了)

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    
        static NSString *cellIdentifier = @"cell";
        customCell *cell = (customCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
        if (cell == nil)
        
            NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"customCell" owner:self options:nil];
            cell = [nib objectAtIndex:0];

        

        leftBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
        leftBtnclick.tag=999;
        [leftBtnclick setImage:[UIImage imageNamed:@"unchecked.png"] forState:UIControlStateNormal];
        [leftBtnclick setImage:[UIImage imageNamed:@"checked.png"] forState:UIControlStateSelected];

        if (screenHeight == 667)
        
            [leftBtnclick setFrame:CGRectMake(50, 59, 30, 30)];
         
        else if(screenHeight == 480)
        
            [leftBtnclick setFrame:CGRectMake(50, 40, 30, 30)];

        

        [leftBtnclick addTarget:self action:@selector(leftTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
        [cell.leftOptBtn addTarget:self action:@selector(leftTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
        [cell.contentView addSubview:leftBtnclick];

        rightBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
        rightBtnclick.tag=1000;
        [rightBtnclick setImage:[UIImage imageNamed:@"unchecked.png"] forState:UIControlStateNormal];
        [rightBtnclick setImage:[UIImage imageNamed:@"checked.png"] forState:UIControlStateSelected];

        if (screenHeight == 667)
        
           [rightBtnclick setFrame:CGRectMake(180, 59, 30, 30)];
        
        else if(screenHeight == 480)
        
            [leftBtnclick setFrame:CGRectMake(50, 40, 30, 30)];

        

        [rightBtnclick setFrame:CGRectMake(180, 59, 30, 30)];
        [rightBtnclick addTarget:self action:@selector(rightTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
        [cell.rightOptBtn addTarget:self action:@selector(rightTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
        [cell.contentView addSubview:rightBtnclick];

        cell.numberLbl.text = [numberArray objectAtIndex:indexPath.row];
        cell.questionLbl.text = [questionArray objectAtIndex:indexPath.row];
        [cell.leftOptBtn setTitle:[leftOptionArray objectAtIndex:indexPath.row] forState:UIControlStateNormal];
        [cell.rightOptBtn setTitle:[rightOptionArray objectAtIndex:indexPath.row] forState:UIControlStateNormal];


            //[1]Set values for left and right 
    rightTickBtn.selected = [RightTicksArray objectAtIndex:indexPath.row];
    leftTickBtn.selected = [LeftTicksArray objectAtIndex:indexPath.row];
        return cell;
    

    -(void)leftTickBtnClicked:(id)sender
    
        UIButton *leftTickBtn=(UIButton *)sender;
        leftTickBtn.selected=!leftTickBtn.selected;
        for(UIView *vw in [[sender superview]subviews])
        
            if([vw isKindOfClass:[UIButton class]] && vw.tag==1000)
            
                UIButton *rightTickBtn=(UIButton *)vw;

                if(leftTickBtn.selected)
                
                    rightTickBtn.selected=NO;
                
                else
                
                    rightTickBtn.selected=YES;
                
//[2]Update RightTickArray At Pos
     [RightTickArray objectAtIndex:indexPath.row] = leftTickBtn.selected;
        
    

    

    -(void)rightTickBtnClicked:(id)sender
    

        UIButton *rightTickBtn=(UIButton *)sender;
        rightTickBtn.selected=!rightTickBtn.selected;


        for(UIView *vw in [[sender superview]subviews])
        
            if([vw isKindOfClass:[UIButton class]] && vw.tag==999)
            
                UIButton *leftTickBtn=(UIButton *)vw;

                if(rightTickBtn.selected)
                
                    leftTickBtn.selected=NO;
                
                else
                
                    leftTickBtn.selected=YES;
                

    //[3]Update LeftTickArray At Pos
        [LeftTicksArray objectAtIndex:indexPath.row] = leftTickBtn.selected;
                
            


    

【讨论】:

您的想法是正确的,但您的代码对我不起作用。修改 2) 和 3) 给出错误 @alex 对不起,我当时没有 Mac 来正确测试它,如果它对你有帮助,请点赞【参考方案3】:

我的问题得到了解决方案。 UITableView 单元格在滚动时可重用,这就是单选按钮选择消失的原因。因此,解决方案是将您的选择存储在一个数组中,并在 cellForRowAtIndexPath 中使用该数组。见代码。

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

    static NSString *cellIdentifier = @"cell";
    customCell *cell = (customCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil)
    

        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"customCell" owner:self options:nil];
        cell = [nib objectAtIndex:0];

    

    leftBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
    leftBtnclick.tag=999;
    cell.leftOptBtn.tag=999;
    [leftBtnclick setImage:[UIImage imageNamed:@"unchecked.png"] forState:UIControlStateNormal];
    [leftBtnclick setImage:[UIImage imageNamed:@"checked.png"] forState:UIControlStateSelected];
    [leftBtnclick setFrame:CGRectMake(50, 59, 30, 30)];
    [leftBtnclick addTarget:self action:@selector(leftTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
    [cell.leftOptBtn addTarget:self action:@selector(leftBtnClicked) forControlEvents:UIControlEventTouchUpInside];
    [cell.contentView addSubview:leftBtnclick];


    rightBtnclick = [UIButton buttonWithType:UIButtonTypeCustom];
    rightBtnclick.tag=1000;
    cell.rightTickBtn.tag=1000;
    [rightBtnclick setImage:[UIImage imageNamed:@"unchecked.png"] forState:UIControlStateNormal];
    [rightBtnclick setImage:[UIImage imageNamed:@"checked.png"] forState:UIControlStateSelected];
    [rightBtnclick setFrame:CGRectMake(190, 59, 30, 30)];


    [rightBtnclick addTarget:self action:@selector(rightTickBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
    [cell.rightOptBtn addTarget:self action:@selector(rightBtnClicked) forControlEvents:UIControlEventTouchUpInside];
    [cell.contentView addSubview:rightBtnclick];

    cell.numberLbl.text = [numberArray objectAtIndex:indexPath.row];
    cell.questionLbl.text = [questionArray objectAtIndex:indexPath.row];
    [cell.leftOptBtn setTitle:[leftOptionArray objectAtIndex:indexPath.row] forState:UIControlStateNormal];
    [cell.rightOptBtn setTitle:[rightOptionArray objectAtIndex:indexPath.row] forState:UIControlStateNormal];

    if ([[answerArray objectAtIndex:indexPath.row] isEqualToString:@"YES"])
    
        leftBtnclick.selected=YES;
        rightBtnclick.selected=NO;

    
    else if ([[answerArray objectAtIndex:indexPath.row] isEqualToString:@"NO"])
    
        leftBtnclick.selected=NO;
        rightBtnclick.selected=YES;
    
    else
    
        leftBtnclick.selected=NO;
        rightBtnclick.selected=NO;
    
    return cell;




-(void)leftTickBtnClicked:(id)sender

    CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:questionTable];
    NSIndexPath *indexPath1 = [questionTable indexPathForRowAtPoint:buttonPosition];
    [answerArray replaceObjectAtIndex:indexPath1.row withObject:@"YES"];

    UIButton *leftTickBtn=(UIButton *)sender;
    leftTickBtn.selected=!leftTickBtn.selected;
    for(UIView *vw in [[sender superview]subviews])
    
        if([vw isKindOfClass:[UIButton class]] && vw.tag==1000)
        
            UIButton *rightTickBtn=(UIButton *)vw;

            if(leftTickBtn.selected)
            
                 rightTickBtn.selected=NO;

            
            else
            
                rightTickBtn.selected=YES;

            


        
    
    NSLog(@"Answer Array: %@",answerArray);


-(void)rightTickBtnClicked:(id)sender

    CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:questionTable];
    NSIndexPath *indexPath1 = [questionTable indexPathForRowAtPoint:buttonPosition];
    [answerArray replaceObjectAtIndex:indexPath1.row withObject:@"NO"];

    UIButton *rightTickBtn=(UIButton *)sender;
    rightTickBtn.selected=!rightTickBtn.selected;


    for(UIView *vw in [[sender superview]subviews])
    
        if([vw isKindOfClass:[UIButton class]] && vw.tag==999)
        
            UIButton *leftTickBtn=(UIButton *)vw;

            if(rightTickBtn.selected)
            
                leftTickBtn.selected=NO;

            
            else
            
                leftTickBtn.selected=YES;

            

        
    
    NSLog(@"Answer Array: %@",answerArray);


【讨论】:

以上是关于滚动 UITableView 时单选按钮未选中的主要内容,如果未能解决你的问题,请参考以下文章

使用 jQuery Sortables 拖动项目时单选按钮被取消选择

如果未选中单选按钮,如何将隐藏字段设置为零

AngularJS - 未选中单选按钮

未选中 Knockout/Jqm 单选按钮

jQuery单选按钮“选中”属性未触发

Material UI:更改未选中单选按钮的颜色