How to implement only single cell selection in eac

2019-06-14 04:17发布

问题:

I have a table view with 5 sections and I have set the tableview selection to multiple. Each section have different number of rows. What I want is to set that the user can select only one cell from each section(in my table user can select any number of cells). ex: 5 cells from 5 sections.

It should be impossible to select more than one cell from any section. If user select another cell from same section, previously selected cell should be deselected. How can I do this. This is a sample implementation of 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);

    }

}

回答1:

You need to keep track on the selection of cell. So you need to store selected indexpath in array.

in ViewController.h declare property like this

@property(nonatomic,strong) NSMutableDictionary *selectionData;

Now in 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);

}

Your numberOfRowsInSection, numberOfSectionsInTableView and titleForHeaderInSection will remain same.

Let me know if you have any query.



回答2:

You can set selection property of tableview from interface builder. Select your tableview in IB and then select attribute inspector and setsingle selectiontoselection` property like below screenshot.

Or you can set programattically,

 self.tableView.allowsMultipleSelection = NO;

Update :

If you want single selection per section then you can implement willSelectRowAtIndexPath as below,

 - (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 ;
}

In this case you should allow multiple selection in tableview i think.

Reference : Answer of John Sauer



回答3:

Looks like you are updating celltwo / cellone selectedsignLabel.hidden on table selection. so @Lion solution will not working. You have to save the last selected index using below code :

@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 ;
}

I have not update the complete working code. But this is the way to achieve. You can also use the userdefault instead of self.selectedIndexPathDict.