0

My app has a multiple choice questions and answers type screen.

For this i have designed screen with UITableView i.e.,In a row i have taken four answers with four radio buttons. Here what is my exact problem is, if while I am selecting one radio button in one row its automatically selecting another row along with what I selected previous. Example in row1 i have selected option2 radio button then here its automatically selecting another row option2 also.

I have tried below code please help me on this. Thanks in Advance.

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
   cell = [_tableViewRef dequeueReusableCellWithIdentifier:@"cell"];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    NSString *rowNumber = [NSString stringWithFormat:@"%ld",(long)indexPath.row+1];
     [[cell questionLbl] setText:[NSString stringWithFormat:@"%@. %@",rowNumber,@"Provide your own fixed background behind the UITableView?"]];
    
  
    [cell.option1RadioBtn addTarget:self
                 action:@selector(radioBtnn1Action:)
       forControlEvents:UIControlEventTouchUpInside];
    [cell.option2RadioBtn addTarget:self
                             action:@selector(radioBtnn2Action:)
                   forControlEvents:UIControlEventTouchUpInside];
    [cell.option3RadioBtn addTarget:self
                             action:@selector(radioBtnn3Action:)
                   forControlEvents:UIControlEventTouchUpInside];
    [cell.option4RadioBtn addTarget:self
                             action:@selector(radioBtnn4Action:)
                   forControlEvents:UIControlEventTouchUpInside];
        return cell;
}

In radio buttons actions i have tried this code:

-(void)radioBtnn1Action:(UIButton*)sender
{
   
    CGPoint center= sender.center;
    CGPoint rootViewPoint = [sender.superview convertPoint:center toView:self.tableViewRef];
    NSIndexPath *indexPath = [self.tableViewRef indexPathForRowAtPoint:rootViewPoint];
    cell = [self.tableViewRef cellForRowAtIndexPath:indexPath];
    


    if ([cell.option1RadioBtn isSelected]) {
        [cell.option1RadioBtn setSelected:YES];
        
        [cell.option2RadioBtn setSelected:NO];
        [cell.option3RadioBtn setSelected:NO];
        [cell.option4RadioBtn setSelected:NO];

    }
    else
    {
        [cell.option1RadioBtn setSelected:YES];
        
        [cell.option2RadioBtn setSelected:NO];
        [cell.option3RadioBtn setSelected:NO];
        [cell.option4RadioBtn setSelected:NO];

    }

    
    
    
}
-(void)radioBtnn2Action:(UIButton*)sender
{
    
    CGPoint center= sender.center;
    CGPoint rootViewPoint = [sender.superview convertPoint:center toView:self.tableViewRef];
    NSIndexPath *indexPath = [self.tableViewRef indexPathForRowAtPoint:rootViewPoint];
    cell = [self.tableViewRef cellForRowAtIndexPath:indexPath];
    

    if ([cell.option2RadioBtn isSelected]) {
        [cell.option2RadioBtn setSelected:YES];
        
        [cell.option1RadioBtn setSelected:NO];
        [cell.option3RadioBtn setSelected:NO];
        [cell.option4RadioBtn setSelected:NO];
        
    }
    else
    {
        [cell.option2RadioBtn setSelected:YES];
        
        [cell.option1RadioBtn setSelected:NO];
        [cell.option3RadioBtn setSelected:NO];
        [cell.option4RadioBtn setSelected:NO];
        
    }
    
    
}
-(void)radioBtnn3Action:(UIButton*)sender
{
    
    CGPoint center= sender.center;
    CGPoint rootViewPoint = [sender.superview convertPoint:center toView:self.tableViewRef];
    NSIndexPath *indexPath = [self.tableViewRef indexPathForRowAtPoint:rootViewPoint];
    cell = [self.tableViewRef cellForRowAtIndexPath:indexPath];
    

    if ([cell.option3RadioBtn isSelected]) {
        [cell.option3RadioBtn setSelected:YES];
        
        [cell.option1RadioBtn setSelected:NO];
        [cell.option2RadioBtn setSelected:NO];
        [cell.option4RadioBtn setSelected:NO];
        
    }
    else
    {
        [cell.option3RadioBtn setSelected:YES];
        
        [cell.option1RadioBtn setSelected:NO];
        [cell.option2RadioBtn setSelected:NO];
        [cell.option4RadioBtn setSelected:NO];
        
    }
    
    
}
-(void)radioBtnn4Action:(UIButton*)sender
{
    
    CGPoint center= sender.center;
    CGPoint rootViewPoint = [sender.superview convertPoint:center toView:self.tableViewRef];
    NSIndexPath *indexPath = [self.tableViewRef indexPathForRowAtPoint:rootViewPoint];
    cell = [self.tableViewRef cellForRowAtIndexPath:indexPath];
    if ([cell.option4RadioBtn isSelected]) {
        [cell.option4RadioBtn setSelected:YES];
        
        [cell.option1RadioBtn setSelected:NO];
        [cell.option2RadioBtn setSelected:NO];
        [cell.option3RadioBtn setSelected:NO];
        
    }
    else
    {
        [cell.option4RadioBtn setSelected:YES];
        
        [cell.option1RadioBtn setSelected:NO];
        [cell.option2RadioBtn setSelected:NO];
        [cell.option3RadioBtn setSelected:NO];
        
    }
    
    
}
Sajida
  • 31
  • 9
  • You should use tag for radiobutton. Like this one:=> option1RadioBtn.tag = 1 so on. And radioBtnn1Action function verify if option1RadioBtn.tag == 1 something like this. – iParesh Feb 27 '17 at 05:29
  • hey @ iParesh thanks for your response can you please post some code snippet here. – Sajida Feb 27 '17 at 05:33
  • you need to create one nsmutablearray than add 4 radio button value by default 0.hwen user can select any one set 1 value for particular radio button index value because this problem is tableview reusablecell problem – Jigar Feb 27 '17 at 05:49
  • Hey @Jigar thanks can please some code here – Sajida Feb 27 '17 at 06:02
  • @Sajida check this http://stackoverflow.com/questions/35402287/how-to-add-json-and-stepper-value-store-in-using-button-click-event-nsmutablearr. in this quetion you got some idea.if any problem than tell me – Jigar Feb 27 '17 at 06:06

2 Answers2

0

There are lots of areas in your code where you can improve and small things can cause this kind of behavior. Am posting your code with the modifications. Please replace your block of code with mine. The problem in your code is you have declared the cell globally and taking the reference of the globally declared table view. The most effective improvement i want you to do in the case of detecting the cell with the button click. You don't need these much code to achieve that. Lets start.

To maintain the selection state we will use the array sectionData.

Add this code to the did load function.

for (int index = 0; index < 10; index ++) {//taken 10 because you are using only 10 rows
    [sectionData addObject:@"0"];
}

and replace your code for the below function completely.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    NSString *rowNumber = [NSString stringWithFormat:@"%ld",(long)indexPath.row+1];
    [[cell questionLbl] setText:[NSString stringWithFormat:@"%@. %@",rowNumber,@"Provide your own fixed background behind the UITableView?"]];

    [cell.option1RadioBtn setSelected:([[sectionData objectAtIndex:indexPath.row] isEqualToString:@"1"])];
    [cell.option2RadioBtn setSelected:([[sectionData objectAtIndex:indexPath.row] isEqualToString:@"2"])];
    [cell.option3RadioBtn setSelected:([[sectionData objectAtIndex:indexPath.row] isEqualToString:@"3"])];
    [cell.option4RadioBtn setSelected:([[sectionData objectAtIndex:indexPath.row] isEqualToString:@"4"])];

    cell.option1RadioBtn.indexPath = indexPath;
    cell.option2RadioBtn.indexPath = indexPath;
    cell.option3RadioBtn.indexPath = indexPath;
    cell.option4RadioBtn.indexPath = indexPath;

    [cell.option1RadioBtn addTarget:self action:@selector(radioBtnnAction:) forControlEvents:UIControlEventTouchUpInside];
    [cell.option2RadioBtn addTarget:self action:@selector(radioBtnnAction:) forControlEvents:UIControlEventTouchUpInside];
    [cell.option3RadioBtn addTarget:self action:@selector(radioBtnnAction:) forControlEvents:UIControlEventTouchUpInside];
    [cell.option4RadioBtn addTarget:self action:@selector(radioBtnnAction:) forControlEvents:UIControlEventTouchUpInside];
        return cell;
}

You can see am using the references of variables inside the function only. And i have taken the target as only 1 function. Now the trick you need to do is make a subclass of UIButton and name it as CustomButton. And also see above for the lines where i have assigned the indexPath to the button properties. Don't forget to change the class for the Outlet and the Element in the storyboard and class file of UITableViewCell.

The .h file for the custom button.

@interface CustomButton : UIButton

@property (nonatomic, strong) NSIndexPath *indexPath;

@end

Now your target function will go like below.

- (void)radioBtnnAction:(CustomButton*)sender
{
    UITableViewCell *cell = [self.tableViewRef cellForRowAtIndexPath:sender.indexPath];
   
    [sectionData replaceObjectAtIndex:sender.indexPath.row withObject:((sender == cell.option1RadioBtn)?@"1":(sender == cell.option2RadioBtn)?@"2":(sender == cell.option3RadioBtn)?@"3":@"4")];

    [cell.option1RadioBtn setSelected:(sender == cell.option1RadioBtn)];
    [cell.option2RadioBtn setSelected:(sender == cell.option2RadioBtn)];
    [cell.option3RadioBtn setSelected:(sender == cell.option3RadioBtn)];
    [cell.option4RadioBtn setSelected:(sender == cell.option4RadioBtn)];
}

I hope i have included everything. Try once.

Mahesh Agrawal
  • 3,348
  • 20
  • 34
  • i missed something in my code. I have edited the answer. please use the latest code block for cellForRowAtIndexPath – Mahesh Agrawal Feb 27 '17 at 05:43
  • hi thank you but here [cell.option1RadioBtn setIndexPath:indexPath]; is showing some error like *no visible@interface for "UIButton" declares the selector 'setIndexpath' * – Sajida Feb 27 '17 at 05:52
  • please refer to the bold lines in the answer. i mentioned you to change the class of those buttons to CustomButton. – Mahesh Agrawal Feb 27 '17 at 05:53
  • also i have edited the same block for better understanding. copy the cellForRowAtIndexPath code again. – Mahesh Agrawal Feb 27 '17 at 05:54
  • Hey mahesh thanks i have tried your code but problem is still their like before while I am selecting one radio button in one row its automatically selecting another row along with what I selected previous. – Sajida Feb 27 '17 at 06:01
  • can you post the only screen in a blank project on git or somewhere? because the code is perfect however you are using some more code which may be the problem – Mahesh Agrawal Feb 27 '17 at 06:03
  • can i get ur mail id i will send you through mail – Sajida Feb 27 '17 at 06:05
  • agrawal.mahesh313@gmail.com – Mahesh Agrawal Feb 27 '17 at 06:07
  • Thank you so much i will send you project. – Sajida Feb 27 '17 at 06:11
  • demo only. and i will also edit the answer with the solution for public. – Mahesh Agrawal Feb 27 '17 at 06:12
  • No problem mahesh please check once your mail then edit your answer in stack over flow.i am newbie to ios development. – Sajida Feb 27 '17 at 06:19
  • edited answer. please replace the whole code of the cellForRowAtIndexPath function please. its working now with your code. – Mahesh Agrawal Feb 27 '17 at 06:45
  • Hey mahesh its working but still small issues while scrolling up the previously selected radio button deselecting automatically please help me on this. – Sajida Feb 27 '17 at 06:55
  • it will disappear because you have not managed their states. tableview cells will be deallocated as soon as you scroll. So you need to store the selected option for each question in an array and you need to change it according to the selection continues. – Mahesh Agrawal Feb 27 '17 at 06:57
  • @Sajida i already tell you you need to store radio button value in array – Jigar Feb 27 '17 at 06:58
  • ok editing answer. please copy the both function codes again to your code and i have added another block to the answer. Use it in did load. – Mahesh Agrawal Feb 27 '17 at 07:02
  • Thanks a lot Mahesh U saved my day – Sajida Feb 27 '17 at 07:07
0

It appears you already have a custom cell.

Rather than exposing a label questionLbl on the cell. Have the cell take a question model. The model could be something like

Class QuestionModel Property question Property selection

Your cell has a property = questionModel AND handles the button selection. So when you assign the question model with the cell property setter, you set the button states as well. Have the button target/action call methods in the cell which update the question model selection property.

You set the cell.question in the tableView source rather than setting a label directly.

The bottom line is, the cell should handle a model not the viewController. It is just there to pass the model to the cell.

Taun
  • 41
  • 2
  • On re-reading your question, the question model should include the answers as properties maybe even as an array. The point being, the QuestionModel should have all the information you need to show the state and record changes to the state. – Taun Feb 27 '17 at 06:48