63

I have an application that is viewbased and I am adding a tableview as a subview to the main view. I have taken UITableViewDelegate to respond the table methods. Everything is working fine, but I want to select the first row or UITableView as default selected(Highlighted).

Please help me, with what code I need and where I need to put it.

Till
  • 27,559
  • 13
  • 88
  • 122
tushar maniyar
  • 641
  • 1
  • 7
  • 7
  • I'm also trying to figure out how to do this. It needs to be set after the UITableViewDataSource functions have been called so the table view has something in it. UITableView doesn't seem to have any callbacks that fire after data is loaded. – jpsimons Nov 27 '10 at 18:46
  • You can do what the correct answer explain [here](https://stackoverflow.com/questions/19295297/uitableviewcell-set-selected-initially/41362393) also you will need to store the selected index somewhere so when scrolling the table view, it behaves as you want – rgkobashi Dec 07 '19 at 08:59

10 Answers10

114
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    NSIndexPath *indexPath=[NSIndexPath indexPathForRow:0 inSection:0];
    [myTableView selectRowAtIndexPath:indexPath animated:YES  scrollPosition:UITableViewScrollPositionBottom];
}

The best way to use this in your code, if you want to select any row by default, use in viewDidAppear.

Kyle Clegg
  • 38,547
  • 26
  • 130
  • 141
Zain Raza
  • 1,299
  • 1
  • 9
  • 17
  • 4
    My cell would not select in viewDidAppear for some strange reason, but it works fine in viewWillAppear – RyanG Dec 13 '12 at 16:20
  • 1
    The app might crash if there is some filter thats happening and it results in empty array. Need to add a check at start – Kaushil Ruparelia Dec 12 '15 at 16:41
  • I'm using this approach to select a cell on first place, then I'm calling the delegate, but the cell selected with selectRowAtIndexPath never gets deselected. Not allowing MultipleSelection. Any help? please, thanks. – Frade Feb 17 '17 at 16:51
  • cell never gets deselected, not even calling deselectRowAtIndexPath – Frade Feb 17 '17 at 17:02
  • solved. call selectRowAtIndexPath on viewDidAppear instead of viewDidLoad. sorry, thanks – Frade Feb 17 '17 at 17:08
12

Swit 3.0 updated Solution

let indexPath = IndexPath(row: 0, section: 0)
tblView.selectRow(at: indexPath, animated: true, scrollPosition: .bottom)
Sourabh Sharma
  • 8,222
  • 5
  • 68
  • 78
8
- (void)viewWillAppear:(BOOL)animated
    {

       [super viewWillAppear:animated];

     // assuming you had the table view wired to IBOutlet myTableView

        // and that you wanted to select the first item in the first section

        [myTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:0];
    }
PR Singh
  • 653
  • 5
  • 15
Ankit Vyas
  • 7,507
  • 13
  • 56
  • 89
5
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];

    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad){
        NSIndexPath* indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
        [self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionTop];
        [self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
    }
}
malhal
  • 26,330
  • 7
  • 115
  • 133
5

Swift 4 Update:

func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    let indexPath = IndexPath(row: 0, section: 0)
    myTableView.selectRow(at: indexPath, animated: true, scrollPosition: .bottom)
}

Change row and section values if you want to select any other row in a different section.

Sanket Ray
  • 1,071
  • 1
  • 15
  • 24
5

Swift 5.x Update:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    let indexPath = IndexPath(row: 0, section: 0)
    tableView.selectRow(at: indexPath, animated: true, scrollPosition: .bottom)
    tableView.delegate?.tableView?(tableView, didSelectRowAt: indexPath)
}
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Ashu
  • 3,373
  • 38
  • 34
3

Here's how to do this in Swift 1.2:

override func viewWillAppear(animated: Bool) {
    let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)
    self.tableView.selectRowAtIndexPath(firstIndexPath, animated: true, scrollPosition: .Top)
}
natec
  • 254
  • 1
  • 3
  • 16
2

Here is my solution for swift 3.0:

var selectedDefaultIndexPath = false


override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    if dataSource.isEmpty == false, selectedDefaultIndexPath == false {
        let indexPath = IndexPath(row: 0, section: 0)
        // if have not this, cell.backgroundView will nil.
        tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
        // trigger delegate to do something.
        _ = tableView.delegate?.tableView?(tableView, willSelectRowAt: indexPath)
        selectedDefaultIndexPath = true
    }
}

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    let cell = tableView.cellForRow(at: indexPath)
    cell?.selectedBackgroundView?.backgroundColor = UIColor(hexString: "#F0F0F0")

    return indexPath
}
jkyin
  • 168
  • 1
  • 12
  • the delegate call definitely solved my issue with selectedBackgroundView not being created. I had to modify the willSelect to recreate my view. override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { let cell = tableView.cellForRow(at: indexPath) let bgColorView = UIView() bgColorView.backgroundColor = #colorLiteral(red: 1, green: 0.596, blue: 0.004, alpha: 1) cell?.selectedBackgroundView = bgColorView return indexPath } – Climbatize Aug 09 '18 at 16:29
1

We use custom background images for the cell based on whether or not it is the first cell... a middle cell or the last cell. That way we get a nice rounded corner look to the whole table. When the row is selected, it swaps out a nice 'highlighted' cell to give the user feed back that they have selected a cell.

UIImage *rowBackground;
UIImage *selectionBackground;
NSInteger sectionRows = [tableView numberOfRowsInSection:[indexPath section]];
NSInteger row = [indexPath row];

if (row == 0 && row == sectionRows - 1)
{
    rowBackground = [UIImage imageNamed:@"topAndBottomRow.png"];
    selectionBackground = [UIImage imageNamed:@"topAndBottomRowSelected.png"];
}
else if (row == 0)
{
    rowBackground = [UIImage imageNamed:@"topRow.png"];
    selectionBackground = [UIImage imageNamed:@"topRowSelected.png"];
}
else if (row == sectionRows - 1)
{
    rowBackground = [UIImage imageNamed:@"bottomRow.png"];
    selectionBackground = [UIImage imageNamed:@"bottomRowSelected.png"];
}
else
{
    rowBackground = [UIImage imageNamed:@"middleRow.png"];
    selectionBackground = [UIImage imageNamed:@"middleRowSelected.png"];
}


((UIImageView *)cell.backgroundView).image = rowBackground;
((UIImageView *)cell.selectedBackgroundView).image = selectionBackground;

If you wish just make the first cell, that which is at indexPath.row == 0, to use a custom background.

This is derived from Matt Gallagher's excellent site

Michael Morrison
  • 1,323
  • 1
  • 18
  • 30
1

To only select the first cell the first time the table is loaded, one would think that using viewDidLoad is the right place to go, but, at that time of execution, the table hasn't loaded its contents, so it will not work (and probably crash the app since the NSIndexPath will point to a non-existent cell).

A workaround is to use a variable that indicates that the table has loaded before and do the work accordingly.

@implementation MyClass {
    BOOL _tableHasBeenShownAtLeastOnce;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    _tableHasBeenShownAtLeastOnce = NO; // Only on first run
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    if ( ! _tableHasBeenShownAtLeastOnce )
    {
        _tableHasBeenShownAtLeastOnce = YES;
        BOOL animationEnabledForInitialFirstRowSelect = YES; // Whether to animate the selection of the first row or not... in viewDidAppear:, it should be YES (to "smooth" it). If you use this same technique in viewWillAppear: then "YES" has no point, since the view hasn't appeared yet.
        NSIndexPath *indexPathForFirstRow = [NSIndexPath indexPathForRow:0 inSection: 0];

        [self.tableView selectRowAtIndexPath:indexPathForFirstRow animated:animationEnabledForInitialFirstRowSelect scrollPosition:UITableViewScrollPositionTop];
    }
}

/* More Objective-C... */

@end
Alejandro Iván
  • 3,969
  • 1
  • 21
  • 30