S.J
S.J

Reputation: 3071

How do you select uitableview rows programmatically

I am trying to achive a email like select all functionality in uitableview where on same button tap user can checkmark or remove all checkmark and additionally user can also select/deselect rows(on didSelectRowAtIndexPath). I tried to do but its not working properly, here is my code.

- (IBAction)selectAll:(id)sender
{
    if(myBoolean)
    {
        for (NSInteger s = 0; s < self.iTable.numberOfSections; s++)
        {
            for (NSInteger r = 0; r < [self.iTable numberOfRowsInSection:s]; r++)
            {
                [[self.iTable cellForRowAtIndexPath:[NSIndexPath indexPathForRow:r inSection:s]] setAccessoryType:UITableViewCellAccessoryNone];
            }
        }

        myBoolean = NO;

        [_selectUnselectButton setTitle:@"Select all Friends" forState:UIControlStateNormal];
    }
    else
    {
        for (NSInteger s = 0; s < self.iTable.numberOfSections; s++)
        {
            for (NSInteger r = 0; r < [self.iTable numberOfRowsInSection:s]; r++)
            {
                [[self.iTable cellForRowAtIndexPath:[NSIndexPath indexPathForRow:r inSection:s]] setAccessoryType:UITableViewCellAccessoryCheckmark];
                NSLog(@"%d-%d",s,r);
            }
        }

        myBoolean = YES;

        [_selectUnselectButton setTitle:@"Unselect all Friends" forState:UIControlStateNormal];
    }
}


-(void)tableView:(UITableView *)tableView_ didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView_ cellForRowAtIndexPath:indexPath];

    [cell setSelectionStyle:UITableViewCellSelectionStyleNone];

    if (cell.accessoryType == UITableViewCellAccessoryCheckmark)
    {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
    else
    {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
}

Upvotes: 2

Views: 22751

Answers (8)

Abdul Karim
Abdul Karim

Reputation: 4523

  • Xcode 8x
  • Swift 3x

    Select Row

    let indexPath = IndexPath(row: 0, section: 0)
    mytableView.selectRow(at: indexPath, animated: true, scrollPosition: .bottom)
    myTableView.delegate?.tableView!(myTableView, didSelectRowAt: indexPath)
    

    DeSelect Row

    let deselectIndexPath = IndexPath(row: 7, section: 0)
    myTableView.deselectRow(at: deselectIndexPath, animated: true)
    myTableView.delegate?.tableView!(tblView, didDeselectRowAt: indexPath)
    

    Upvotes: 0

  • Siba Prasad Hota
    Siba Prasad Hota

    Reputation: 4789

    Take another NSMutableArray as SelectedArray

    in didSelectRowAtIndexPath row You can Add remove objects from SelectedArray.

    You can select a UITableViewCell calling UITableViews selectRowAtIndexPath method:

    [yourtable selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] 
                           animated:NO 
                     scrollPosition:UITableViewScrollPositionTop];
    

    Put for loop for selectedArray to putcheckmark only in selected cells or All cells.

    check my accepted answer here : Need to create a select all button for UITableView and add selections to an array in iOS

    Upvotes: 0

    vikingosegundo
    vikingosegundo

    Reputation: 52227

    I wrote a sample code that I adapted to your needs.

    Basically it is

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *unifiedID = @"aCellID";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:unifiedID];
        if (!cell) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:unifiedID];
        }
    
        cell.textLabel.text = [self.states objectAtIndex:indexPath.row];
    
        //if the indexPath was found among the selected ones, set the checkmark on the cell
        cell.accessoryType = ([self isRowSelectedOnTableView:tableView atIndexPath:indexPath]) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
        return cell;
    
    }
    
    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        NSString *state = [self.states objectAtIndex:indexPath.row];
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        if([self isRowSelectedOnTableView:tableView atIndexPath:indexPath]){
            [self.selectedCells removeObject:indexPath];
            [self.selecedStates removeObject:state];
            cell.accessoryType = UITableViewCellAccessoryNone;
        } else {
            [self.selectedCells addObject:indexPath];
            [self.selecedStates addObject:state];
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
        }
    
        NSLog(@"%@", self.selecedStates);
    }
    
    
    -(BOOL)isRowSelectedOnTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath
    {
        return ([self.selectedCells containsObject:indexPath]) ? YES : NO;
    }
    
    
    - (IBAction)selectAll:(id)sender {
    
        [self.selecedStates removeAllObjects];
        [self.selectedCells removeAllObjects];
        NSUInteger numberOfSections = [self.tableView numberOfSections];
        for (NSUInteger s = 0; s < numberOfSections; ++s) {
            NSUInteger numberOfRowsInSection = [self.tableView numberOfRowsInSection:s];
            for (NSUInteger r = 0; r < numberOfRowsInSection; ++r) {
                NSIndexPath *idxPath = [NSIndexPath indexPathForRow:r inSection:s];
                [self.selectedCells addObject:idxPath];
                [self.selecedStates addObject:self.states[idxPath.row]];
            }
        }
        [self.tableView reloadData];
    }
    
    
    
    - (IBAction)deselectAll:(id)sender {
        [self.selecedStates removeAllObjects];
        [self.selectedCells removeAllObjects];
        [self.tableView reloadData];
    }
    
    
    - (IBAction)toggleAll:(id)sender {
        if ([self.states count] == [self.selecedStates count]) {
            [sender setTitle:@"select all"];
            [self deselectAll:sender];
        } else {
            [sender setTitle:@"deselect all"];
            [self selectAll:sender];
       }
    }
    

    in action:

    enter image description here

    You are calling

    [[self.iTable cellForRowAtIndexPath:[NSIndexPath indexPathForRow:r inSection:s]] setAccessoryType:UITableViewCellAccessoryNone];
    

    for every row in every section within the tableView. if you have many row, this is ver inefficient, as it will deal with rows not on the screen. But this is not needed. just put every selected index path into an array and tell the tableView to reload. This will reload the visible cells and due to the implementation of -tableView:cellForRowAtIndexPath: cells wfor new rows will be correctly re-conigured.

    Upvotes: 8

    Hemang
    Hemang

    Reputation: 27050

    You can follow these steps to implement this,

    1) You should have a mutable array to store indexpaths

    2) What you can do is, when you tap Check All or Uncheck All, do add or remove all indexpaths to/from array (which you've), reload table for update changes

    3) In - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath datasource method, check into array using if([array containsObject:indexPath]), if exist mark it checked or unchecked

    4) In - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath delegate method, you should check for already existence of indexpath tapped into array, as you've did in 3rd step, and add or remove indexpaths as per the condition, reload table for update changes

    Upvotes: 0

    Sergey Kalinichenko
    Sergey Kalinichenko

    Reputation: 726499

    Setting the accessory view needs to happen inside the tableView:cellForRowAtIndexPath: method. When you want to change the accessories from outside, the outside method needs to change the model first to indicate that check marks must be placed in certain cells, and then call reloadData on the UITableView.

    One way to store what cells are checked is an array of NSIndexSet objects - one index set per section. In the example below I show code for a single section, but you should get an idea of how to make multiple sections work.

    // This variable needs to be declared in a place where your data source can get it
    NSMutableIndexSet *selected;
    
    // You need to initialize it in the designated initializer, like this:
    selected = [[NSMutableIndexSet alloc] init];
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        }
        if ([selected containsIndex:indexPath.row]) {
            [cell setAccessoryType:UITableViewCellAccessoryCheckmark];
        } else {
            [cell setAccessoryType:UITableViewCellAccessoryNone];
        }
        // Do the rest of your code
        return cell;
    }
    

    Now in the code where you want to set rows selected or unselected you just need to call [selected addIndex:rowToSelect] or [selected removeIndex:rowToUnselect], and call your table's reloadData.

    Upvotes: 5

    Dixit Patel
    Dixit Patel

    Reputation: 3192

    Try this code instead of your old one

    - (IBAction)selectAll:(id)sender
    {
        if(myBoolean)
        {
            for (NSInteger s = 0; s < self.iTable.numberOfSections; s++)
            {
                for (NSInteger r = 0; r < [self.iTable numberOfRowsInSection:s]; r++)
                {
                  [self.iTable selectRowAtIndexPath:[NSIndexPath indexPathForRow:r inSection:s]] animated:YES scrollPosition:UITableViewScrollPositionNone];
    
                }
            }
    
            myBoolean = NO;
    
            [_selectUnselectButton setTitle:@"Select all Friends" forState:UIControlStateNormal];
        }
        else
        {
            for (NSInteger s = 0; s < self.iTable.numberOfSections; s++)
            {
                for (NSInteger r = 0; r < [self.iTable numberOfRowsInSection:s]; r++)
                {
                     [self.iTable selectRowAtIndexPath:[NSIndexPath indexPathForRow:r inSection:s]] animated:YES scrollPosition:UITableViewScrollPositionNone];
                    NSLog(@"%d-%d",s,r);
                }
            }
    
            myBoolean = YES;
    
            [_selectUnselectButton setTitle:@"Unselect all Friends" forState:UIControlStateNormal];
        }
    }
    
    
    -(void)tableView:(UITableView *)tableView_ didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView_ cellForRowAtIndexPath:indexPath];
    
        [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
    
        if (cell.accessoryType == UITableViewCellAccessoryCheckmark)
        {
            cell.accessoryType = UITableViewCellAccessoryNone;
        }
        else
        {
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
        }
    }
    

    Upvotes: 2

    lakshmen
    lakshmen

    Reputation: 29064

    you can do something like this:

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        [self doSomethingWithRowAtIndexPath:indexPath];
    }
    

    Upvotes: -1

    Inder Kumar Rathore
    Inder Kumar Rathore

    Reputation: 39978

    Use selectRowAtIndexPath:animated:scrollPosition: to select a row
    and deselectRowAtIndexPath:animated: to deselect a row.
    For more read the UITableView docs

    Upvotes: 3

    Related Questions