How to select UITableView cell programmatically (Swift 2) - ios

I have an UITableViewController and I need to select and scroll to one of the cells when the view loads. The reason I need the cell selected rather than just making it look selected (with an accessory or whatever) is that I want it to have a different background and no separators above/below (which is what happens when a table cell is selected), and I want the cell initially visible (if it's too far down).
I've read the two other answers and they don't work or I don't understand them. I'm not sure where I should put the self.tableView.selectRowAtIndexPath and self.scrollToRowAtIndexPath. I tried putting it in viewDidLoad() and it had no effect.

Try to use viewDidAppear
func viewDidAppear(animated: Bool){
super.viewDidAppear(animated)
let path = NSIndexPath(forRow: 1, inSection: 0)
tableView.selectRowAtIndexPath(myPath, animated: false, scrollPosition: UITableViewScrollPosition.None)
}

Swift 4:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let path = IndexPath(row: 0, section: 0)
tableView.selectRow(at: path, animated: false, scrollPosition: .none)
}

Use the selectRowAtIndexPath method of UITableView in your view controller's viewDidAppear method
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
// replace forRow: value with the index of the cell
// replace inSection: value with the section the cell is in
let indexPath = NSIndexPath(forRow: 2, inSection: 0)
tableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: .Middle)
}

Given solutions didn't work for me. So, here is the solution for swift 5
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
//Choose the row and section
let indexPath = IndexPath(row: 0, section: 0)
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .middle)
tableView.delegate?.tableView!(tableView, didSelectRowAt: indexPath)
}

Related

Swift tableViewCell stays selected

When I go selected a cell in my VC and go to another VC, and then back again to the first VC, the cell is still selected. I found some answers here and on the Medium but they didn't work.
I tried this in didSelectRowAt but it makes no sense because I will never be able to select a row if I put this at the beginning of the method:
tableView.deselectRow(at: indexPath, animated: false)
I also found this solution but it didn't work, too:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let selectedRow: IndexPath? = tableView.indexPathForSelectedRow
if let selectedRow = selectedRow {
tableView.deselectRow(at: selectedRow, animated: true)
}
else {
print("no selected rows found")
}
}
The method above always prints no selected rows found

Setting UITableView row selection programmatically returns nil

Trying to call a TableView row to be selected programatically.
All my delegates are set properly, and the UITableView is linked in IB. All other UITableView methods work properly, and are located in either the main ViewController or its extension. When the following is called I get Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value.
func selectTableViewRowProgrammatically () {
let indexPath = IndexPath(row: someVariable, section: 0)
tableView.selectRow(at: indexPath, animated: false, scrollPosition: UITableView.ScrollPosition.none)
tableView.delegate?.tableView!(self.tableView, didSelectRowAt: indexPath)
tableView.reloadData()
}
Error shows on self.tableView.selectRow(at: indexPath, animated: false, scrollPosition: UITableView.ScrollPosition.none)
Thanks!
can you try Following code
let indexPath = IndexPath(row: someVariable, section: 0)
UIView.animate(withDuration: 0.1, animations: {
tableView.scrollToRow(at: indexPath, at: .top, animated: false)
}) { (true) in
tableView.delegate?.tableView!(self.tableView, didSelectRowAt: indexPath)
}

Horizontal Scrolling collection View issue

I am trying to scroll horizontally to a collectionView when I call a function and am receiving the error 'none' is unavailable: use [] to construct an empty option set - not sure what is wrong here...Thanks in advance!
func handleSearch() {
scrollToMenuIndex(menuIndex: 2)
}
func scrollToMenuIndex(menuIndex: Int) {
let indexPath = NSIndexPath(item: menuIndex, section: 0)
collectionView?.scrollToItem(at: indexPath as IndexPath, at: .none, animated: true)
}
You have to provide a position where the item should be scrolled to. See the documentation for UICollectionViewScrollPosition for possible values. In the meantime you could use this:
collectionView?.scrollToItem(at: indexPath as IndexPath, at: .left, animated: true)

How to programmatically select a row in UITableView in Swift

I need to select a row in a UITableView programmatically using Swift 1.2.
This is the simple code:
var index = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.selectRowAtIndexPath(index, animated: true, scrollPosition: UITableViewScrollPosition.Middle)
self.tableView(self.tableView, didSelectRowAtIndexPath: index)
The above gives me the following error:
Cannot invoke 'selectRowAtIndexPath' with an argument list of type '(NSIndexPath!, animated: Bool, scrollPosition: UITableViewScrollPosition)'
What is wrong with my Swift 1.2 code?
My UItableView has been created in IB in the UIViewController that I am trying to call the code above.
When I put the code in a UITableViewController the compiler does not give any errors.
Do I need to embed a UITableViewController in a container or is there another way?
Swift 3 to Swift 5 Solution
Selecting a Row
let indexPath = IndexPath(row: 0, section: 0)
myTableView.selectRow(at: indexPath, animated: true, scrollPosition: .bottom)
myTableView.delegate?.tableView!(myTableView, didSelectRowAt: indexPath)
DeSelecting a Row
let deselectIndexPath = IndexPath(row: 7, section: 0)
myTableView.deselectRow(at: deselectIndexPath, animated: true)
myTableView.delegate?.tableView!(myTableView, didDeselectRowAt: indexPath)
The statement
self.tableView.selectRowAtIndexPath(index, animated: true, scrollPosition: UITableViewScrollPosition.Middle)
assumes that tableView is a property of the view controller, connected
to a table view in the Storyboard. A UITableViewController, for example, already has this
property.
In your case, the view controller is a not a table view controller
but a subclass of a UIViewController. It also has an outlet that is
connected to the table view, but it is not called
tableView but menuTable. Then of course you have to call
self.menuTable.selectRowAtIndexPath(index, animated: true, scrollPosition: UITableViewScrollPosition.Middle)
to select a row of that table view.
The strange error messages are caused by the fact that
self.tableView can also be understood by the compiler as a
"curried function" (compare http://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/).
Use below code,after loading your table view with data:
let rowToSelect:NSIndexPath = NSIndexPath(forRow: 0, inSection: 0); //slecting 0th row with 0th section
self.tableView.selectRowAtIndexPath(rowToSelect, animated: true, scrollPosition: UITableViewScrollPosition.None);
now,you have to manually call didSelectRowAtIndexPath: delegate method using below code:
self.tableView(self.tableView, didSelectRowAtIndexPath: rowToSelect); //Manually trigger the row to select
Thanks.
Swift 3.x
if you want to do it at the 'cell-creation', you can do it like this
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = TableViewCell()
let item = items[indexPath.row]
cell.textLabel?.text = item.title
if (item.checked) {
tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
}
return cell
}
Using Swift 2.x, as described by Pankaj purohit answers the correct method is:
func tapRowAtIndex(index:Int) {
let rowToSelect:NSIndexPath = NSIndexPath(forRow: index, inSection: 0)
self.tableView.selectRowAtIndexPath(rowToSelect, animated: true, scrollPosition: UITableViewScrollPosition.None)
self.tableView(self.tableView, didSelectRowAtIndexPath: rowToSelect)
}
Keep in mind that if you call this method from an external class for example, you dont know when tableView has finished its loading, so what's the possibilities?, how to workaround this problem? :
Step one: create a class boolean var
var automatingTap: Bool = false
Step two: check when the table finish its loading and launch an "end operations" method:
func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
{
let lastRowIndex = tableView.numberOfRowsInSection(0)
if indexPath.row == lastRowIndex - 1 {
endOperations()
}
}
func endOperations()
{
print("finished loading")
if automatingTap {
tapRowAtIndex(0)
automatingTap = false
}
}
Step three: call my tableView class from another class
for example:
override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
if segue!.identifier == "DetailsTableView" {
let viewController:ViewController = segue!.destinationViewController as ViewController
viewController.automatingTap = true
}
}
Reusable function with validation of table size
Swift 4 and 5
This reusable function works and validate the size of table.
func selectRow(tableView: UITableView, position: Int) {
let sizeTable = tableView.numberOfRows(inSection: 0)
guard position >= 0 && position < sizeTable else { return }
let indexPath = IndexPath(row: position, section: 0)
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .middle)
}
you can use it in this way
selectRow(tableView: myTableView, position: pos)
or you can implement this extension:
extension UITableView {
func selectRow(row: Int, section: Int = 0) {
let sizeTable = self.numberOfRows(inSection: section)
guard row >= 0 && row < sizeTable else { return }
let indexPath = IndexPath(row: row, section: section)
self.selectRow(at: indexPath, animated: true, scrollPosition: .middle)
}
}
and you can use it in this way:
mytableView.selectRow(row: pos, section: 0)
or
mytableView.selectRow(row: pos)
Swift 4.2:
Select one or more Rows
let ndx:IndexSet = [1]
// or: let ndx:IndexSet = [1, 2, 3]; // etc
tableview?.selectRowIndexes(ndx, byExtendingSelection: false);
Deselect a Single Row
tableview?.deselectRow(current)
Note that if you have (func tableViewSelectionDidChange(...)) implemented, that will be triggered by the above.
Also see Charlton Provatas' answer at https://stackoverflow.com/a/48696458/352920 for an extension to NSTableView, that provides a simple
tableview?.selectRow(at:)

IOS/Swift: Save the cell selection on UITableView

I have a master detail layout with table views in both of the views. Left panel has a list of patients and right has a list of documents, what happens is by changing the patient selection documents will be reloaded and if the user clicks on a document, it will segue to a webView to display PDF.
For consistency purpose i made the first cell in the Patient table to be selected by default using the below code
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(true)
let rowToSelect:NSIndexPath = NSIndexPath(forRow: 0, inSection: 0);
self.tableView.selectRowAtIndexPath(rowToSelect, animated: true, scrollPosition: UITableViewScrollPosition.None)
self.performSegueWithIdentifier("showDetail", sender: self)
}
work's fine right?, Yes but it gets a bit inconsistent from here, after closing this PDF document (by clicking done on navigation), my Previously selected cell will go off and it again points to the first Patient. Is there any way to save this selection? Oh and even to save the selection on the details page too. Thanks.
Create an NSIndexPath property.
Change your viewDidAppear to only default-select the first cell if there wasn't something previously selected:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(true)
if (!self.rowToSelect) {
rowToSelect = NSIndexPath(forRow: 0, inSection: 0);
self.tableView.selectRowAtIndexPath(rowToSelect, animated: true, scrollPosition: UITableViewScrollPosition.None)
self.performSegueWithIdentifier("showDetail", sender: self)
}
}
In the didSelectRow delegate method store the selected index path in self.rowToSelect.

Resources