Select one row in each section of UITableView ios?

Scenario:

I made 2 sections in one UITableView and the user needs to select a row in each section as shown in the screenshot below.

Expected result: 1. The user should be able to select a row in each section

Result right now: 1. After I select a row in one section and then when I select a row in the second section, the first selection disappears.

Here is my code:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Uncheck the previous checked row

    long sec=indexPath.section;
     if(sec==0){
    if(self->checkedIndexPath)
    {
        UITableViewCell* uncheckCell = [tableView
                                        cellForRowAtIndexPath:self->checkedIndexPath];
        uncheckCell.accessoryType = UITableViewCellAccessoryNone;
    }
    if([self->checkedIndexPath isEqual:indexPath])
    {
        self->checkedIndexPath = nil;
    }
    else
    {
        UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        self->checkedIndexPath = indexPath;
    }}

    if(sec==1){

        if(self->checkedIndexPath)
        {
            UITableViewCell* uncheckCell = [tableView
                                            cellForRowAtIndexPath:self->checkedIndexPath];
            uncheckCell.accessoryType = UITableViewCellAccessoryNone;
        }
        if([self->checkedIndexPath isEqual:indexPath])
        {
            self->checkedIndexPath = nil;
        }
        else
        {
            UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
            self->checkedIndexPath = indexPath;
        }

    }

}

      

Help is appreciated.

+2


source to share


3 answers


This is the easiest way. I finally found a solution. This works for me, hope it works for you. declare these

@interface ViewController ()
{
    int selectedsection;
    NSMutableArray *selectedindex;

}

      



Replace didSelectRowAtIndexPath as follows:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Uncheck the previous checked row

    NSIndexPath *selectedIndexPath = [tableView indexPathForSelectedRow];

        if(self.checkedIndexPath)

        {

            for (int i=0; i<[selectedindex count]; i++) {

                NSIndexPath *temp= [selectedindex objectAtIndex:i];
                if (temp.section==selectedIndexPath.section) {
                    UITableViewCell* uncheckCell = [tableView
                                                    cellForRowAtIndexPath:temp];
                    uncheckCell.accessoryType = UITableViewCellAccessoryNone;

                }
            }

            NSInteger numb= [tableView numberOfRowsInSection:selectedIndexPath.section];

            if (selectedsection==selectedIndexPath.section) {


            UITableViewCell* uncheckCell = [tableView
                                            cellForRowAtIndexPath:self.checkedIndexPath];
            uncheckCell.accessoryType = UITableViewCellAccessoryNone;

            }
        }



        if([self.checkedIndexPath isEqual:indexPath])
        {
            for (int i=0; i<[selectedindex count]; i++) {

                NSIndexPath *temp= [selectedindex objectAtIndex:i];
                if (temp.section==selectedIndexPath.section) {
                    UITableViewCell* uncheckCell = [tableView
                                                    cellForRowAtIndexPath:temp];
                    uncheckCell.accessoryType = UITableViewCellAccessoryNone;

                }
            }


           self.checkedIndexPath = nil;
        }
        else
        {
            for (int i=0; i<[selectedindex count]; i++) {

                NSIndexPath *temp= [selectedindex objectAtIndex:i];
                if (temp.section==selectedIndexPath.section) {
                    UITableViewCell* uncheckCell = [tableView
                                                    cellForRowAtIndexPath:temp];
                    uncheckCell.accessoryType = UITableViewCellAccessoryNone;

                }
            }

            UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
            self.checkedIndexPath = indexPath;
            [selectedindex addObject:indexPath];
            selectedsection=indexPath.section;

            NSLog(@"check");
        }






}

      

+1


source


You can enable multiple selection in the table view:



self.tableView.allowsMultipleSelection = YES;

      

0


source


I wrote a sample code where a composite data source stores data source objects for each section. It sounds complicated, but it actually makes it easy to extend the architecture. And keeps your view controller small.

The advantages of this approach:

  • Small ViewController
  • ViewController configures the view and handles user interaction - as it should in MVC
  • Reusable data sources
  • using different data sources in a section it is easy to customize cells for each section

basic data source architecture

This makes it easy to expand and easy to reuse.


@import UIKit;

@interface ComoundTableViewDataSource : NSObject
@property (nonatomic,strong, readonly) NSMutableDictionary *internalDictionary;


-(void) setDataSource:(id<UITableViewDataSource>)dataSource forSection:(NSUInteger)section;
-(instancetype)initWithTableView:(UITableView *)tableView;
@end

      


#import "ComoundTableViewDataSource.h"


@interface ComoundTableViewDataSource () <UITableViewDataSource>
@property (nonatomic,strong, readwrite) NSMutableDictionary *internalDictionary;
@property (nonatomic, weak) UITableView *tableView;
@end

@implementation ComoundTableViewDataSource
-(instancetype)initWithTableView:(UITableView *)tableView
{
    self = [super init];
    if (self) {
        _tableView = tableView;
        tableView.dataSource = self;
        _internalDictionary = [@{} mutableCopy];
        [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];

    }
    return self;
}

-(void)setDataSource:(id<UITableViewDataSource>)dataSource forSection:(NSUInteger)section
{
    self.internalDictionary[@(section)] = dataSource;
    [self.tableView reloadData];

}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [[self.internalDictionary allKeys] count];
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    id<UITableViewDataSource> sectionDataSource = self.internalDictionary[@(section)];
    return [sectionDataSource tableView:tableView numberOfRowsInSection:section];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    id<UITableViewDataSource> sectionDataSource = self.internalDictionary[@(indexPath.section)];
    return [sectionDataSource tableView:tableView cellForRowAtIndexPath:indexPath];

}


-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    id<UITableViewDataSource> sectionDataSource = self.internalDictionary[@(section)];
    return [sectionDataSource tableView:tableView titleForHeaderInSection:section];
}
@end

      


@import UIKit;

@interface SingleSectionDataSource : NSObject <UITableViewDataSource>
@property (nonatomic, strong, readonly) NSArray *array;
@property (nonatomic, strong, readonly) UITableView *tableView;

- (instancetype)initWithArray:(NSArray *)array;
@end

      


#import "SingleSectionDataSource.h"

@interface SingleSectionDataSource ()
@property (nonatomic, strong, readwrite) NSArray *array;
@property (nonatomic, strong, readwrite) UITableView *tableView;

@end

@implementation SingleSectionDataSource

- (instancetype)initWithArray:(NSArray *)array
{
    self = [super init];
    if (self) {
        self.array = array;
    }
    return self;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    self.tableView = tableView;
    return self.array.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    cell.textLabel.text = self.array[indexPath.row];
    return cell;
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return [@(section) stringValue];
}

@end

      

selection data source architecture

We are extending the classes from above to allow one selection per section

#import "ComoundTableViewDataSource.h"

@interface OnSelectionPerSectionComoundTableViewDataSource : ComoundTableViewDataSource
-(void)selectedCellAtIndexPath:(NSIndexPath *)indexPath;

@end

      


#import "OnSelectionPerSectionComoundTableViewDataSource.h"
#import "SingleSelectionSingleSectionDataSource.h"

@implementation OnSelectionPerSectionComoundTableViewDataSource


-(instancetype)initWithTableView:(UITableView *)tableView
{
    self = [super initWithTableView:tableView];
    if(self){
        [tableView setAllowsMultipleSelection:YES];
    }
    return self;
}

-(void)selectedCellAtIndexPath:(NSIndexPath *)indexPath
{
    SingleSelectionSingleSectionDataSource *sectionDataSource = self.internalDictionary[@(indexPath.section)];
    [sectionDataSource selectedCellAtIndexPath:indexPath];
}
@end

      

View controller implementation

As promised, a very thin controller:

@interface ViewController () <UITableViewDelegate>
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (nonatomic, strong) OnSelectionPerSectionComoundTableViewDataSource *tableViewDataSource;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.tableViewDataSource = [[OnSelectionPerSectionComoundTableViewDataSource alloc] initWithTableView:self.tableView];
    self.tableView.delegate = self;
    [self.tableViewDataSource setDataSource:[[SingleSelectionSingleSectionDataSource alloc] initWithArray:@[@"Hallo", @"Welt"]] forSection:0];
    [self.tableViewDataSource setDataSource:[[SingleSelectionSingleSectionDataSource alloc] initWithArray:@[@"Hello", @"World", @"!"]] forSection:1];
    [self.tableViewDataSource setDataSource:[[SingleSelectionSingleSectionDataSource alloc] initWithArray:@[@"Hola", @"Mundo", @"!", @"¿Que tal?"]] forSection:2];
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [self.tableViewDataSource selectedCellAtIndexPath:indexPath];
}
@end

      

You need to add methods to data sources to get the selected rows.

take an example: https://github.com/vikingosegundo/CompoundDatasourceExample

Note This code has a cell reuse issue. It is pinned to GitHub.

0


source







All Articles