Select ALL TableView Rows Programmatically Using selectRowAtIndexPath
Solution 1
At the time allJobsSelected
becomes true, you need to call the UITableView
method selectRowAtIndexPath(_:animated:scrollPosition:)
for each row of your table. In my case, I attached this functionality to the right bar button item which I named Select All
. Calling this from cellForRowAtIndexPath
is surely not the right place.
@IBAction func doSelectAll(sender: UIBarButtonItem) {
let totalRows = tableView.numberOfRowsInSection(0)
for row in 0..<totalRows {
tableView.selectRowAtIndexPath(NSIndexPath(forRow: row, inSection: 0), animated: false, scrollPosition: UITableViewScrollPosition.None)
}
}
Solution 2
For Swift 3 and answering your question literally, regardless of your code.
func selectAllRows() {
for section in 0..<tableView.numberOfSections {
for row in 0..<tableView.numberOfRows(inSection: section) {
tableView.selectRow(at: IndexPath(row: row, section: section), animated: false, scrollPosition: .none)
}
}
}
If you want to inform the tableview delegate, use this method:
func selectAllRows() {
for section in 0..<tableView.numberOfSections {
for row in 0..<tableView.numberOfRows(inSection: section) {
let indexPath = IndexPath(row: row, section: section)
_ = tableView.delegate?.tableView?(tableView, willSelectRowAt: indexPath)
tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
tableView.delegate?.tableView?(tableView, didSelectRowAt: indexPath)
}
}
}
Solution 3
Functional solution (Swift 5.1)
extension UITableViewDataSource where Self: UITableView {
/**
* Returns all IndexPath's in a table
* ## Examples:
* table.indexPaths.forEach {
* selectRow(at: $0, animated: true, scrollPosition: .none) // selects all cells
* }
*/
public var indexPaths: [IndexPath] {
return (0..<self.numberOfSections).indices.map { (sectionIndex: Int) -> [IndexPath] in
(0..<self.numberOfRows(inSection: sectionIndex)).indices.compactMap { (rowIndex: Int) -> IndexPath? in
IndexPath(row: rowIndex, section: sectionIndex)
}
}.flatMap { $0 }
}
}
![Tom](https://lh4.googleusercontent.com/-lhRPWoCsd1g/AAAAAAAAAAI/AAAAAAAAIzU/U1sLQ7PONYE/photo.jpg?sz=256)
Tom
Updated on July 14, 2022Comments
-
Tom almost 2 years
I'm trying to programmatically select all rows in my tableview using the following code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell:myTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! myTableViewCell cell.accessoryType = .None if allJobsSelected { let bgColorView = UIView() bgColorView.backgroundColor = UIColor(red: 250/255, green: 182/255, blue: 17/255, alpha: 1) cell.contentView.backgroundColor = UIColor(red: 250/255, green: 182/255, blue: 17/255, alpha: 1) cell.selectedBackgroundView = bgColorView cell.accessoryType = .Checkmark cell.highlighted = false cell.selected = true // cell.accessoryType = .Checkmark self.tableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: UITableViewScrollPosition.None) self.tableView(self.tableView, didSelectRowAtIndexPath: indexPath) } var job: Jobs! job = jobs[UInt(indexPath.row)] as! Jobs cell.reports2JobTitle.text = job.jobTitle return cell } func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { self.tableView.allowsMultipleSelection = true if let cell:myTableViewCell = tableView.cellForRowAtIndexPath(indexPath) as? myTableViewCell { let bgColorView = UIView() bgColorView.backgroundColor = UIColor(red: 250/255, green: 182/255, blue: 17/255, alpha: 1) cell.contentView.backgroundColor = UIColor(red: 250/255, green: 182/255, blue: 17/255, alpha: 1) cell.selectedBackgroundView = bgColorView cell.accessoryType = .Checkmark cell.highlighted = false self.tableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: UITableViewScrollPosition.Bottom) } }
My issue is that only the rows that have been dequeued are added to my table's data model when I segue to the next viewcontroller. In order to add all the rows to my table's data model I have to manually scroll through the whole table. How can I change this so all the selected rows are added to my table's data model without having to scroll through the whole table?
What I cannot understand is that after all my rows are selected I then loop through my indexPaths as follows but not all of the indexPaths are added unless I first scroll through the entire table.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) { if (segue.identifier == "reportsDisplay") { let controller = segue.destinationViewController as! ReportsDisplayViewController var selectedJob : Jobs! if let indexPaths = tableView.indexPathsForSelectedRows { for i in 0 ..< indexPaths.count { let thisPath = indexPaths[i] selectedJob = jobs[UInt(thisPath.row)] as! Jobs let jobTitle = selectedJob.jobTitle let id = selectedJob.identifier jobsToReport.append(jobTitle) jobsID.append(id) } } controller.reportedJobs = jobsToReport controller.idOfJobs = jobsID } }
-
Tom almost 8 yearsYou're right, I do have gaps in my knowledge. I have added my prepareForSegue function to illustrate. What I don't understand is that within my prepareForSegue function I loop through my indexPaths and I seem to have to make sure that the cell has been dequeued before it is added to my data model. There must be a cleaner method of all my selected cells getting added without me having to manually scroll through the table.
-
vacawama almost 8 yearsIt's not clear from your code when
allJobsSelected
becomes true, but at the time that happens, you should callselectRowAtIndexPath
for every row of your table. That will mark the row selected. It is not necessary to scroll to the row or load the data. -
Sipho Koza over 6 yearsBrilliant - Thank you for the solution!
-
rommex over 2 yearsIntersecting
UITableViewDataSource
andUITableView
is not a good idea