141

How do I programmatically select a UITableView row so that

- (void)tableView:(UITableView *)tableView 
        didSelectRowAtIndexPath:(NSIndexPath *)indexPath

gets executed? selectRowAtIndexPath will only highlight the row.

Alex Cio
  • 6,014
  • 5
  • 44
  • 74
4thSpace
  • 43,672
  • 97
  • 296
  • 475
  • I encountered the same issue and just fine the link: http://stackoverflow.com/questions/5324501/select-tableviews-row-from-an-another-view I hope it will be helpful for you. – michael Jun 16 '12 at 14:12

7 Answers7

120

Like Jaanus told:

Calling this (-selectRowAtIndexPath:animated:scrollPosition:) method does not cause the delegate to receive a tableView:willSelectRowAtIndexPath: or tableView:didSelectRowAtIndexPath: message, nor will it send UITableViewSelectionDidChangeNotification notifications to observers.

So you just have to call the delegate method yourself.

For example:

Swift 3 version:

let indexPath = IndexPath(row: 0, section: 0);
self.tableView.selectRow(at: indexPath, animated: false, scrollPosition: UITableViewScrollPosition.none)
self.tableView(self.tableView, didSelectRowAt: indexPath)

ObjectiveC version:

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView selectRowAtIndexPath:indexPath 
                            animated:YES 
                      scrollPosition:UITableViewScrollPositionNone];
[self tableView:self.tableView didSelectRowAtIndexPath:indexPath];

Swift 2.3 version:

 let indexPath = NSIndexPath(forRow: 0, inSection: 0);
 self.tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: UITableViewScrollPosition.None)
 self.tableView(self.tableView, didSelectRowAtIndexPath: indexPath)
Rahul Vyas
  • 28,260
  • 49
  • 182
  • 256
Dulgan
  • 6,674
  • 3
  • 41
  • 46
112

From reference documentation:

Calling this method does not cause the delegate to receive a tableView:willSelectRowAtIndexPath: or tableView:didSelectRowAtIndexPath: message, nor does it send UITableViewSelectionDidChangeNotification notifications to observers.

What I would do is:

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

And then, from where you wanted to call selectRowAtIndexPath, you instead call doSomethingWithRowAtIndexPath. On top of that, you can additionally also call selectRowAtIndexPath if you want the UI feedback to happen.

Pang
  • 9,564
  • 146
  • 81
  • 122
Jaanus
  • 17,688
  • 15
  • 65
  • 110
  • 4
    Or when you select the row programmatically, you could call tableView:didSelectRowAtIndexPath: yourself (in the class you have wired as the delegate). – Kendall Helmstetter Gelner Jan 10 '10 at 02:21
  • 3
    This method seems like a hack to me , it did get the job done but i think there should be a better way of doing it . – Tapan Thaker Oct 26 '12 at 16:45
  • 1
    I don't really think you need to create a call "doSomethingWithRowAtIndexPath" can't you just call the delegate method and pass the arguments you need to execute the didSelect logic from the place where you implemented the delegate method? – ImpactZero Dec 12 '14 at 19:18
63

UITableView's selectRowAtIndexPath:animated:scrollPosition: should do the trick.

Just pass UITableViewScrollPositionNone for scrollPosition and the user won't see any movement.


You should also be able to manually run the action:

[theTableView.delegate tableView:theTableView didSelectRowAtIndexPath:indexPath]

after you selectRowAtIndexPath:animated:scrollPosition: so the highlight happens as well as any associated logic.

Srikar Appalaraju
  • 71,928
  • 54
  • 216
  • 264
anq
  • 3,102
  • 21
  • 16
  • Sorry, that is what I'm using. I accidentally put scrollToRowAtIndexPath. I've updated the question. scrollToRowAtIndexPath only highlights the cell. – 4thSpace Jan 09 '10 at 22:02
  • 2
    Yeah, I'm sorry. It says it won't fire didSelectRowAtIndexPath right there in the docs link I posted. I need to learn to read. – anq Jan 09 '10 at 22:17
  • @anq: Thank you very much! It helps me when I call the didSelectRowAtIndexPath:indexPath in the custom cell. – Bentley Sep 11 '15 at 04:47
22

Swift 3/4/5 Solution

Select Row

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

DeSelect Row

let deselectIndexPath = IndexPath(row: 7, section: 0)
tblView.deselectRow(at: deselectIndexPath, animated: true)
tblView.delegate?.tableView!(tblView, didDeselectRowAt: indexPath)
N. Der
  • 507
  • 4
  • 18
Sourabh Sharma
  • 8,222
  • 5
  • 68
  • 78
21

if you want to select some row this will help you

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[someTableView selectRowAtIndexPath:indexPath 
                           animated:NO 
                     scrollPosition:UITableViewScrollPositionNone];

This will also Highlighted the row. Then delegate

 [someTableView.delegate someTableView didSelectRowAtIndexPath:indexPath];
Alex Cio
  • 6,014
  • 5
  • 44
  • 74
Nazir
  • 1,945
  • 24
  • 27
4

There are two different methods for iPad and iPhone platforms, so you need to implement both:

  • selection handler and
  • segue.

    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    [self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
    
    // Selection handler (for horizontal iPad)
    [self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
    
    // Segue (for iPhone and vertical iPad)
    [self performSegueWithIdentifier:"showDetail" sender:self];
    
Alexander Volkov
  • 7,904
  • 1
  • 47
  • 44
3

Use this category to select a table row and execute a given segue after a delay.
Call this within your viewDidAppear method:

[tableViewController delayedSelection:withSegueIdentifier:]


@implementation UITableViewController (TLUtils)

-(void)delayedSelection:(NSIndexPath *)idxPath withSegueIdentifier:(NSString *)segueID {
    if (!idxPath) idxPath = [NSIndexPath indexPathForRow:0 inSection:0];                                                                                                                                                                 
    [self performSelector:@selector(selectIndexPath:) withObject:@{@"NSIndexPath": idxPath, @"UIStoryboardSegue": segueID } afterDelay:0];                                                                                               
}

-(void)selectIndexPath:(NSDictionary *)args {
    NSIndexPath *idxPath = args[@"NSIndexPath"];                                                                                                                                                                                         
    [self.tableView selectRowAtIndexPath:idxPath animated:NO scrollPosition:UITableViewScrollPositionMiddle];                                                                                                                            

    if ([self.tableView.delegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)])
        [self.tableView.delegate tableView:self.tableView didSelectRowAtIndexPath:idxPath];                                                                                                                                              

    [self performSegueWithIdentifier:args[@"UIStoryboardSegue"] sender:self];                                                                                                                                                            
}

@end
j0k
  • 22,600
  • 28
  • 79
  • 90