如何在iOS,Objective C的tableview中的每个部分中仅实现单个单元格选择

Posted

技术标签:

【中文标题】如何在iOS,Objective C的tableview中的每个部分中仅实现单个单元格选择【英文标题】:How to implement only single cell selection in each section in the tableview in iOS, Objective C 【发布时间】:2016-07-06 10:02:41 【问题描述】:

我有一个包含 5 个部分的表格视图,并且我已将表格视图选择设置为多个。每个部分都有不同的行数。我想要设置用户只能从每个部分中选择一个单元格(在我的表格中,用户可以选择任意数量的单元格)。 例如:5 个部分的 5 个单元格。

应该不可能从任何部分选择多个单元格。如果用户从同一部分选择另一个单元格,则应取消选择先前选择的单元格。我怎样才能做到这一点。这是 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);

    


【问题讨论】:

您是希望只允许从整个表格中选择一项,还是每节选择一项? 每个部分选择一个@Lion 你这里有多少个自定义单元格? 你有 5 个部分。所以我认为一个自定义单元格对你来说就足够了。 我建议让 tableview 多选并根据选择的部分进行验证。 (即不允许在同一部分中进行其他选择) 【参考方案1】:

您需要跟踪单元格的选择。所以你需要将选定的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);


您的numberOfRowsInSectionnumberOfSectionsInTableViewtitleForHeaderInSection 将保持不变。

如果您有任何疑问,请告诉我。

【讨论】:

谢谢你,选择工作正常。这意味着如果我从第一部分选择它不会影响其他人。现在问题是,用户可以从同一部分中选择更多。我赞成这个。 所以你想限制用户在同一部分选择多个单元格? 是的。这就是我需要的 @bill 更新了答案。更新了方法handleSelectionForSection。请检查。 @Hatim 在这种情况下,您必须从 selectionData 字典中删除所选部分旁边的所有部分数据。因此,如果您选择第二部分中的任何行,则从 selectionData > 选定部分索引中删除所有部分条目。如果您不明白,请告诉我。【参考方案2】:

您可以在界面生成器中设置表格视图的selection 属性。在 IB 中选择您的 tableview,然后选择attribute inspector and setsingle selectiontoselection` 属性,如下图所示。

或者您可以通过编程方式设置,

 self.tableView.allowsMultipleSelection = NO;

更新:

如果您希望每个部分单选,那么您可以实现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 中进行多项选择。

参考:Answer of John Sauer

【讨论】:

这个答案正确解释了如何在表格视图中实现单选。不幸的是,这不是 OP 所要求的 - 他们希望能够在任何给定时间为每个部分选择一行。 参考答案是操作者想要的。 @LeXeR :是的,这就是原始帖子想要的! 如果每个部分的行数少于 5,这可以正常工作。如果不是 ex :if I select first row from first section it select, and fifth cell from the section 1 and same select from section 2 also. 我没有得到你在评论中所说的内容。究竟会发生什么?【参考方案3】:

看起来您正在更新表选择时的 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。

【讨论】:

以上是关于如何在iOS,Objective C的tableview中的每个部分中仅实现单个单元格选择的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS(Swift 或 Objective C)中实现这样的套接字调用?

如何从 AudioUnits C 函数调用 Objective-C 方法? (iOS)

如何使用 Objective C 在 iOS 上本地下载和保存文件? [复制]

Objective c 如何在ios13中将方向设置为横向

iOS:Objective -C如何在应用程序处于后台模式时更改推送通知声音有效负载?

IOS/Objective C:如何根据数据自定义画面