Peter Pik
Peter Pik

Reputation: 11193

Select a row at view load

I'm trying to pre select a table row when the view load, however i have tried several methods, but none seem to work. At first i've set following two methods in order to define the textColor changes when a row is selected and deselected

open func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    let cell = menuCells[indexPath.row]

    cell.textLabel?.textColor = UIColor.white.withAlphaComponent(0.4)
}

open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let cell = menuCells[indexPath.row]

    cell.textLabel?.textColor = UIColor.white.withAlphaComponent(1.0)

    UIApplication.shared.sendAction(cell.menuAction, to: cell.menuTarget, from: cell, for: nil)
}

Then i've tried to do following things to preselect a row but it does not seem to change the textColor with alpha to 1.0

open func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {

    if indexPath.row == 0 {
        cell.setSelected(true, animated: false)
    }
}



menuView.selectRow(at: IndexPath(row: 0, section: 0), animated: false, scrollPosition: UITableViewScrollPosition.none)

Upvotes: 1

Views: 2169

Answers (4)

xdzc
xdzc

Reputation: 1471

I think it's most appropriate to select the row in the viewWillAppear method as the view must have been fully initialized.

The example below selects the first cell of the first section:

override func viewWillAppear(_ animated: Bool) {
    let selectedIndexPath = IndexPath(row: 0, section: 0)
    tableView.selectRow(at: selectedIndexPath, animated: true, scrollPosition: UITableViewScrollPosition.none)
    tableView(tableView, didSelectRowAt: selectedIndexPath)
}

Upvotes: 0

jhabbott
jhabbott

Reputation: 19281

Remember that tableView(_:didSelectRowAt:) is part of a delegate protocol designed to handle user interactions with the UITableView instance. It is therefore called in response to user interaction, not programatic changes.

To resolve this, move your appearance changes into a separate function called something like applyAppearanceSelected and call this when you make programatic changes, and also call it from tableView(_:didSelectRowAt:) to handle user-initiated changes. I would not recommend calling tableView(_:didSelectRowAt:) directly yourself, because you might want to add other code there that only applies when the user selects a cell.

Upvotes: 0

Wilson
Wilson

Reputation: 9136

According Apple's documentation:

Calling selectRowAtIndexPath does not cause the delegate to receive a tableView(:willSelectRowAt:) or tableView(:didSelectRowAt:) message

https://developer.apple.com/reference/uikit/uitableview/1614875-selectrowatindexpath


So in viewDidAppear method you should call manually didSelectRowAtIndexPath like in the example below:

class ViewController: UIViewController {

  @IBOutlet weak var myTableView: UITableView!


  override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)


    let indexPath = NSIndexPath(forRow: 2, inSection: 0)

    myTableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: .None)

    // Calling manually to the delegate method
    tableView(myTableView, didSelectRowAtIndexPath: indexPath)
  }

}


// UITableView Delegate Implementation
extension ViewController: UITableViewDataSource, UITableViewDelegate {

  func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
    let cell = tableView.cellForRowAtIndexPath(indexPath)
    cell?.textLabel?.textColor = UIColor.blackColor()
  }

  func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let cell = tableView.cellForRowAtIndexPath(indexPath)
    cell?.textLabel?.textColor = UIColor.redColor()
    cell?.textLabel?.backgroundColor = UIColor.clearColor()
  }

  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 10
  }

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)

    cell.textLabel?.text = String(indexPath.row)

    return cell
  }
}

Result:

image

Upvotes: 2

meowmeowmeow
meowmeowmeow

Reputation: 762

Is this what you're after?

override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        let iPath = NSIndexPath(forRow: 0, inSection: 0)
        tableView.selectRowAtIndexPath(iPath, animated: true, scrollPosition: .Top )
    }

Upvotes: 1

Related Questions