问题
Scenario:
I have made 2 sections in one UITableView and the user needs to select a row in each section as shown in the screenshot below.
Expected Outcome: 1. User should be able to select a row in each section
Outcome right now: 1. After I have selected row in one section, and then when I select the row in 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.
回答1:
This is the simplest way. Finally i found a solution. It works for me, hope it will work 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");
        }
}
回答2:
You can enable the multiple selection in the tableview:
self.tableView.allowsMultipleSelection = YES;
回答3:
I wrote a sample code where a compound datasource holds datasource objects for each section. Sounds complicated but actually provides an easy to extend architecture. And keeps your view controller small.
The advantages of this approach:
- Small ViewController
- ViewController set ups view and handles user interaction — as it should be in MVC
- Reusable datasources
- by using different datasources per section easy to customize cells for each section
the base datasource architecture
This provides easy extension and is simple 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
the selection datasource architecture
We extend 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 slim view 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 will want to add methods to the datasources to get the selected rows.
get the example: https://github.com/vikingosegundo/CompoundDatasourceExample
Note This code has a cell reuse issue. It is fixed on GitHub.
来源:https://stackoverflow.com/questions/27838390/select-one-row-in-each-section-of-uitableview-ios