Search code examples
iphonesavestateuitableviewcheckmark

Set one check mark for each section in UITableView and save its state


Spent hours and hours and no use.I don't understand whether I was not effective in searching(googling) or is it that there are less questions on this or I might have committed some mistake while implementing the answers of experts!

I know there are several questions on setting accessory type check mark for one row and none for other rows in a section,traced out posts here and there.

I have 2 sections in my table view.By default I want the 1st row in each section to be selected i.e. with accessory view check mark.Now from here upon user selection of a row,I want the check mark to be visible on selected row only.I have tried declaring two index paths to keep track of row selection in each section.Here is my implementation code:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{    
    NSString *cellIdentifier = [NSString stringWithFormat:@"S%1dR%1d",indexPath.row,indexPath.section];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (indexPath.section == 0)
    {
        if(self.firstSectionIndex == indexPath)
        {
            cell.accessoryType = UITableViewCellAccessoryNone;
        }
        else
        {
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
        }
    }

    if (indexPath.section == 1)
    {
        if(self.secondSectionIndex == indexPath)
        {
            cell.accessoryType = UITableViewCellAccessoryNone;
        }
        else
        {
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
        }
    }

    if (cell == nil)
    {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
        cell.backgroundColor = [UIColor clearColor];
        cell.textLabel.textColor = [UIColor whiteColor];

        switch (indexPath.section)
        {
            case 0:
            {
                if (indexPath.row == 0)
                {
                    if(self.firstSectionIndex != indexPath)
                    {
                        cell.accessoryType = UITableViewCellAccessoryCheckmark;
                    }
                    else
                    {
                        cell.accessoryType = UITableViewCellAccessoryNone;
                    }
                    cell.textLabel.text = @"Yes";
                }
                if (indexPath.row == 1)
                {
                    cell.textLabel.text = @"No";
                }
            }
                break;
            case 1:
            {
                if (indexPath.row == 0)
                {
                    if(self.secondSectionIndex != indexPath)
                    {
                        cell.accessoryType = UITableViewCellAccessoryCheckmark;
                    }
                    else
                    {
                        cell.accessoryType = UITableViewCellAccessoryNone;
                    }
                    cell.textLabel.text = @"Easy";
                }
                if (indexPath.row == 1)
                {
                    cell.textLabel.text = @"Medium";
                }
                if (indexPath.row == 2)
                {
                    cell.textLabel.text = @"Hard";
                }
            }
                break;

            default:
                break;
        }
    }

    tableView.backgroundColor = [UIColor clearColor];
    tableView.backgroundView = nil;

    return cell;
}

in my didSelectRowAtIndexPath,I have done the following:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0)
    {
      self.firstSectionIndex = indexPath;
    }
    if (indexPath.section == 1)
    {
       self.secondSectionIndex = indexPath;
    }
    [tableView reloadData];
}

I have searched for the state of cell selection to be saved for long term reference,in quest of it,I found some useful link here.

But it is selecting multiple cells and accessory type check mark is being applied for all rows in section.I don't understand what's wrong.Can any one please guide me on this!!

Thanks all in advance :)


Solution

  • I have found a precise and perfect solution,thanks to Lithu T.V and Nithin Gobel for guiding me in the right direction.Unfortunately their solutions didn't help me in achieving 1 check mark per section,but multiple check marks in fact.So I thought of saving the selected row in user defaults and for initially selecting 1st row of each section,we declare first and second section index,assign to index path and then assign cell accessory view as check mark.Here we go,let's first deal with cellForRowAtIndexPath:

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        NSString *cellIdentifier = [NSString stringWithFormat:@"S%1dR%1d",indexPath.row,indexPath.section];
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    
        if (cell == nil)
        {
            cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
            cell.backgroundColor = [UIColor clearColor];
            cell.textLabel.textColor = [UIColor whiteColor];
            NSUserDefaults *savedState = [NSUserDefaults standardUserDefaults];
    
            switch (indexPath.section)
            {
                case 0:
                {
                    NSNumber *indexNumber = [NSNumber numberWithInteger:indexPath.row];
                    if([[savedState objectForKey:@"firstSectionIndex"] isEqual: indexNumber])
                    {
                        cell.accessoryType = UITableViewCellAccessoryCheckmark;
                        self.firstSectionIndex = indexPath;
                    }
    
                    if (indexPath.row == 0)
                    {                    
                        NSObject * checkedCellObject = [savedState objectForKey:@"firstSectionIndex"];
                        if(checkedCellObject == nil)
                        {
                            self.firstSectionIndex = indexPath;
                            cell.accessoryType = UITableViewCellAccessoryCheckmark;
                        }
                        cell.textLabel.text = @"Yes";
                    }
                    if (indexPath.row == 1)
                    {
                        cell.textLabel.text = @"No";
                    }
                }
                    break;
                case 1:
                {
                    NSNumber *indexNumber = [NSNumber numberWithInteger:indexPath.row];
                    if([[savedState objectForKey:@"secondSectionIndex"] isEqual: indexNumber])
                    {
                        cell.accessoryType = UITableViewCellAccessoryCheckmark;
                        secondSectionIndex = indexPath;
                    }
    
                    if (indexPath.row == 0)
                    {
                        NSObject * checkedCellObject = [savedState objectForKey:@"secondSectionIndex"];
                        if(checkedCellObject == nil)
                        {
                            cell.accessoryType = UITableViewCellAccessoryCheckmark;
                            secondSectionIndex = indexPath;
                        }
                        cell.textLabel.text = @"Easy";
                    }
                    if (indexPath.row == 1)
                    {
                        cell.textLabel.text = @"Medium";
                    }
                    if (indexPath.row == 2)
                    {
                        cell.textLabel.text = @"Hard";
                    }
                }
                    break;
    
                default:
                    break;
            }
        }
    
        tableView.backgroundColor = [UIColor clearColor];
        tableView.backgroundView = nil;
    
        return cell;
    }
    

    Please observe in each case,we are checking if the checked state is in saved user defaults,if it is nil,we check 1st cell(row) of each section,here we go with table view delegate method,did select row at index path:

    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
    
        if (indexPath.section == 0)
        {
            UITableViewCell *checkCell = [tableView cellForRowAtIndexPath:indexPath];
            if(firstSectionIndex && firstSectionIndex != indexPath)
            {
                UITableViewCell *uncheckCell = [tableView cellForRowAtIndexPath:firstSectionIndex];
                uncheckCell.accessoryType = UITableViewCellAccessoryNone;
            }
            self.firstSectionIndex = indexPath;
            [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:firstSectionIndex.row] forKey:@"firstSectionIndex"];
            checkCell.accessoryType = UITableViewCellAccessoryCheckmark;
        }
    
        if (indexPath.section == 1)
        {
            UITableViewCell *checkCell = [tableView cellForRowAtIndexPath:indexPath];
            if(secondSectionIndex)
            {
                UITableViewCell *unchekCell = [tableView cellForRowAtIndexPath:secondSectionIndex];
                unchekCell.accessoryType = UITableViewCellAccessoryNone;
            }
            self.secondSectionIndex = indexPath;
            [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:secondSectionIndex.row] forKey:@"secondSectionIndex"];
            checkCell.accessoryType = UITableViewCellAccessoryCheckmark;
        }
    }
    

    That's it,we have successfully accomplished one check mark per section and also save the accessory state of cell in user defaults for long term reference.

    Hope this helps some one,thanks :)