如何在 iOS、Objective C 的表格视图的每个部分中仅实现单个单元格选择
How to implement only single cell selection in each section in the tableview in iOS, Objective C
我有一个包含 5 个部分的 table 视图,并且我已将 table 视图 selection 设置为多个。每个部分都有不同的行数。我想要的是设置用户可以 select 每个部分只有一个单元格(在我的 table 用户可以 select 任意数量的单元格)。
例如:来自 5 个部分的 5 个单元格。
应该不可能 select 来自任何部分的多个单元格。如果用户 select 来自同一部分的另一个单元格,则之前 selected 的单元格应该被删除 selected。我怎样才能做到这一点。这是 didSelectRowAtIndexPath 的示例实现。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
HoteldetalcelloneTableViewCell *cellone = (HoteldetalcelloneTableViewCell *)[self.detailtableView cellForRowAtIndexPath:indexPath];
HoteldetailcelltwoTableViewCell *celltwo = (HoteldetailcelltwoTableViewCell *)[self.detailtableView cellForRowAtIndexPath:indexPath];
//I have implement for two sections to test.
if(indexPath.section == 0)
{
HotelDetailsone *secone = [roomonearray objectAtIndex:indexPath.row];
HoteldetailsforBooking *book = [HoteldetailsforBooking new];
if([secone.offerallow isEqualToString:@"True"])
{
celltwo.selectedsignLabel.hidden = NO;
}
else
{
cellone.selectedsignLabelone.hidden = NO;
}
// [self.detailtableView reloadData];
NSLog(@"price for room 1 : %@", secone.itempriceText);
}
else
{
HotelDetailsone *sectwo = [roomtwoarray objectAtIndex:indexPath.row];
HoteldetailsforBooking *book = [HoteldetailsforBooking new];
if([sectwo.offerallow isEqualToString:@"True"])
{
celltwo.selectedsignLabel.hidden = NO;
}
else
{
cellone.selectedsignLabelone.hidden = NO;
}
// [self.detailtableView reloadData];
NSLog(@"price for room 1 : %@", sectwo.itempriceText);
}
}
您可以从界面生成器中设置表视图的 selection
属性。 Select 你在 IB 中的 tableview,然后 select attribute inspector and set
single selectionto
selection` 属性 如下图所示。
或者您可以通过编程方式设置,
self.tableView.allowsMultipleSelection = NO;
更新:
如果你想要每个部分单个 selection 那么你可以按如下方式实施 willSelectRowAtIndexPath
,
- (NSIndexPath*)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath*)indexPath {
for ( NSIndexPath* selectedIndexPath in tableView.indexPathsForSelectedRows ) {
if ( selectedIndexPath.section == indexPath.section )
[tableView deselectRowAtIndexPath:selectedIndexPath animated:NO] ;
}
return indexPath ;
}
在这种情况下,我认为你应该在 tableview
中允许多个 selection。
参考:Answer of John Sauer
您似乎正在更新 table 选择的 celltwo / cellone selectedsignLabel.hidden。所以@Lion 解决方案将不起作用。您必须使用以下代码保存最后选择的索引:
@property (nonatomic, strong) NSMutableDictionary *selectedIndexPathDict;
// in viewDidLoad:
self.tableView.allowsMultipleSelection = YES;
self.selectedIndexPathDict = [[NSMutableDictionary alloc] init];
//In table view delegate.
- (NSIndexPath*)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath*)indexPath {
NSString *indexSection = [NSString stringWithFormat:@"%ld", (long)indexPath.section];
NSIndexPath *indexPath1 = self.selectedIndexPathDict[indexSection];
if ( indexPath1) {
HotelDetailsone *secone = [roomonearray objectAtIndex:indexPath.row];
secone.offerallow ^= YES; //toggle bool value
// update new selected index path.
[self.selectedIndexPathDict setObject:indexPath forKey:indexSection];
//reload previous selected cell.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(),^{
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:@[indexPath1] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
});
} else {
//initialise selected index path
self.selectedIndexPathDict[indexSection] = indexPath;
}
[tableView deselectRowAtIndexPath:indexPath animated:NO] ;
return indexPath ;
}
我还没有更新完整的工作代码。但这是实现的方式。您也可以使用 userdefault 代替 self.selectedIndexPathDict.
您需要跟踪单元格的选择。因此,您需要将选定的 indexpath
存储在数组中。
在ViewController.h
中这样声明属性
@property(nonatomic,strong) NSMutableDictionary *selectionData;
现在 ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.selectionData=[[NSMutableDictionary alloc]init];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
TestTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"mycell"];
if ([self.selectionData objectForKey:[NSString stringWithFormat:@"%ld",(long)indexPath.section] ] != nil) {
NSMutableArray *sectionData=[[self.selectionData objectForKey:[NSString stringWithFormat:@"%ld",(long)indexPath.section]] mutableCopy];
if (![sectionData containsObject:[NSNumber numberWithLong:indexPath.row]])
{
cell.accessoryType = UITableViewCellAccessoryNone;
cell.numberlabel.text = @"2";
}
else
{
cell.numberlabel.text = @"***";
cell.accessoryType=UITableViewCellAccessoryCheckmark;
}
}
else
{
cell.numberlabel.text = @"2";
cell.accessoryType = UITableViewCellAccessoryNone;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"selected section :%li ---> selected row :%li",(long)indexPath.section, (long)indexPath.row);
[self handleSelectionForSection:indexPath.section row:indexPath.row];
[self.tablev reloadData];
}
-(void)handleSelectionForSection:(long)sectionIndex row:(long)rowIndex
{
if ([self.selectionData objectForKey:[NSString stringWithFormat:@"%ld",sectionIndex] ] != nil) {
NSMutableArray *sectionData=[[self.selectionData objectForKey:[NSString stringWithFormat:@"%ld",sectionIndex]] mutableCopy];
if (![sectionData containsObject:[NSNumber numberWithLong:rowIndex]])
{
//removing previous selected rows
[sectionData removeAllObjects];
[sectionData addObject:[NSNumber numberWithLong:rowIndex]];
[self.selectionData setObject:sectionData forKey:[NSString stringWithFormat:@"%ld",sectionIndex]];
}
else
{
//cell you tapped is already selected,
// you can deselect it by removing object
//if you dont want to deselect it comment following lines
[sectionData removeObject:[NSNumber numberWithLong:rowIndex]];
[self.selectionData setObject:sectionData forKey:[NSString stringWithFormat:@"%ld",sectionIndex]];
}
}
else
{
//section key not available so we need to create it
NSMutableArray *sectionData=[[NSMutableArray alloc]init];
[sectionData addObject:[NSNumber numberWithLong:rowIndex]];
[self.selectionData setObject:sectionData forKey:[NSString stringWithFormat:@"%ld",sectionIndex]];
}
NSLog(@"All Selection : %@",self.selectionData);
}
您的 numberOfRowsInSection
、numberOfSectionsInTableView
和 titleForHeaderInSection
将保持不变。
如果您有任何疑问,请告诉我。
我有一个包含 5 个部分的 table 视图,并且我已将 table 视图 selection 设置为多个。每个部分都有不同的行数。我想要的是设置用户可以 select 每个部分只有一个单元格(在我的 table 用户可以 select 任意数量的单元格)。 例如:来自 5 个部分的 5 个单元格。
应该不可能 select 来自任何部分的多个单元格。如果用户 select 来自同一部分的另一个单元格,则之前 selected 的单元格应该被删除 selected。我怎样才能做到这一点。这是 didSelectRowAtIndexPath 的示例实现。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
HoteldetalcelloneTableViewCell *cellone = (HoteldetalcelloneTableViewCell *)[self.detailtableView cellForRowAtIndexPath:indexPath];
HoteldetailcelltwoTableViewCell *celltwo = (HoteldetailcelltwoTableViewCell *)[self.detailtableView cellForRowAtIndexPath:indexPath];
//I have implement for two sections to test.
if(indexPath.section == 0)
{
HotelDetailsone *secone = [roomonearray objectAtIndex:indexPath.row];
HoteldetailsforBooking *book = [HoteldetailsforBooking new];
if([secone.offerallow isEqualToString:@"True"])
{
celltwo.selectedsignLabel.hidden = NO;
}
else
{
cellone.selectedsignLabelone.hidden = NO;
}
// [self.detailtableView reloadData];
NSLog(@"price for room 1 : %@", secone.itempriceText);
}
else
{
HotelDetailsone *sectwo = [roomtwoarray objectAtIndex:indexPath.row];
HoteldetailsforBooking *book = [HoteldetailsforBooking new];
if([sectwo.offerallow isEqualToString:@"True"])
{
celltwo.selectedsignLabel.hidden = NO;
}
else
{
cellone.selectedsignLabelone.hidden = NO;
}
// [self.detailtableView reloadData];
NSLog(@"price for room 1 : %@", sectwo.itempriceText);
}
}
您可以从界面生成器中设置表视图的 selection
属性。 Select 你在 IB 中的 tableview,然后 select attribute inspector and set
single selectionto
selection` 属性 如下图所示。
或者您可以通过编程方式设置,
self.tableView.allowsMultipleSelection = NO;
更新:
如果你想要每个部分单个 selection 那么你可以按如下方式实施 willSelectRowAtIndexPath
,
- (NSIndexPath*)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath*)indexPath {
for ( NSIndexPath* selectedIndexPath in tableView.indexPathsForSelectedRows ) {
if ( selectedIndexPath.section == indexPath.section )
[tableView deselectRowAtIndexPath:selectedIndexPath animated:NO] ;
}
return indexPath ;
}
在这种情况下,我认为你应该在 tableview
中允许多个 selection。
参考:Answer of John Sauer
您似乎正在更新 table 选择的 celltwo / cellone selectedsignLabel.hidden。所以@Lion 解决方案将不起作用。您必须使用以下代码保存最后选择的索引:
@property (nonatomic, strong) NSMutableDictionary *selectedIndexPathDict;
// in viewDidLoad:
self.tableView.allowsMultipleSelection = YES;
self.selectedIndexPathDict = [[NSMutableDictionary alloc] init];
//In table view delegate.
- (NSIndexPath*)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath*)indexPath {
NSString *indexSection = [NSString stringWithFormat:@"%ld", (long)indexPath.section];
NSIndexPath *indexPath1 = self.selectedIndexPathDict[indexSection];
if ( indexPath1) {
HotelDetailsone *secone = [roomonearray objectAtIndex:indexPath.row];
secone.offerallow ^= YES; //toggle bool value
// update new selected index path.
[self.selectedIndexPathDict setObject:indexPath forKey:indexSection];
//reload previous selected cell.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(),^{
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:@[indexPath1] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
});
} else {
//initialise selected index path
self.selectedIndexPathDict[indexSection] = indexPath;
}
[tableView deselectRowAtIndexPath:indexPath animated:NO] ;
return indexPath ;
}
我还没有更新完整的工作代码。但这是实现的方式。您也可以使用 userdefault 代替 self.selectedIndexPathDict.
您需要跟踪单元格的选择。因此,您需要将选定的 indexpath
存储在数组中。
在ViewController.h
中这样声明属性
@property(nonatomic,strong) NSMutableDictionary *selectionData;
现在 ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.selectionData=[[NSMutableDictionary alloc]init];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
TestTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"mycell"];
if ([self.selectionData objectForKey:[NSString stringWithFormat:@"%ld",(long)indexPath.section] ] != nil) {
NSMutableArray *sectionData=[[self.selectionData objectForKey:[NSString stringWithFormat:@"%ld",(long)indexPath.section]] mutableCopy];
if (![sectionData containsObject:[NSNumber numberWithLong:indexPath.row]])
{
cell.accessoryType = UITableViewCellAccessoryNone;
cell.numberlabel.text = @"2";
}
else
{
cell.numberlabel.text = @"***";
cell.accessoryType=UITableViewCellAccessoryCheckmark;
}
}
else
{
cell.numberlabel.text = @"2";
cell.accessoryType = UITableViewCellAccessoryNone;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"selected section :%li ---> selected row :%li",(long)indexPath.section, (long)indexPath.row);
[self handleSelectionForSection:indexPath.section row:indexPath.row];
[self.tablev reloadData];
}
-(void)handleSelectionForSection:(long)sectionIndex row:(long)rowIndex
{
if ([self.selectionData objectForKey:[NSString stringWithFormat:@"%ld",sectionIndex] ] != nil) {
NSMutableArray *sectionData=[[self.selectionData objectForKey:[NSString stringWithFormat:@"%ld",sectionIndex]] mutableCopy];
if (![sectionData containsObject:[NSNumber numberWithLong:rowIndex]])
{
//removing previous selected rows
[sectionData removeAllObjects];
[sectionData addObject:[NSNumber numberWithLong:rowIndex]];
[self.selectionData setObject:sectionData forKey:[NSString stringWithFormat:@"%ld",sectionIndex]];
}
else
{
//cell you tapped is already selected,
// you can deselect it by removing object
//if you dont want to deselect it comment following lines
[sectionData removeObject:[NSNumber numberWithLong:rowIndex]];
[self.selectionData setObject:sectionData forKey:[NSString stringWithFormat:@"%ld",sectionIndex]];
}
}
else
{
//section key not available so we need to create it
NSMutableArray *sectionData=[[NSMutableArray alloc]init];
[sectionData addObject:[NSNumber numberWithLong:rowIndex]];
[self.selectionData setObject:sectionData forKey:[NSString stringWithFormat:@"%ld",sectionIndex]];
}
NSLog(@"All Selection : %@",self.selectionData);
}
您的 numberOfRowsInSection
、numberOfSectionsInTableView
和 titleForHeaderInSection
将保持不变。
如果您有任何疑问,请告诉我。