How can I reset cell selections in a UITableView?
Use case:
I have a ViewController with a UITableView. I select a cell and I enter another View Controller. When I come back to the TableViewController, I still see the selected cell. I would like to reset any selection.
In:
override func tableView (tableView:UITableView, didSelectRowAtIndexPath indexPath:NSIndexPath)
You could do the following:
tableView.deselectRowAtIndexPath(indexPath, animated:false)
Related
Normally when a UITableViewController that is embedded in a UINavigationController, is returned to from it's detail screen the previously selected row's highlight fades away.
I am trying to replicate this behaviour when a UITableViewController is loaded by a UIPageViewController, but have been unsuccessful so far.
To be clear, my hierarchy when in the detail screen is: UINavigationController>UIPageViewController>UITableViewController>DetailController
Putting the deselectRow:atIndexPath: table view method in the viewDidAppear of the UITableViewController as viewDidAppear is not called. Putting it in the same method, but of the UIPageViewController works, but there is a noticeable delay before the selection fades away.
Has anyone managed to get this to work properly?
Are you referring to UITableView or UITableViewController here
I am trying to replicate this behaviour when a
UITableViewController is loaded by a UINavigationController, but have been unsuccessful so far.
If its a UITableViewController, then it has this clearsSelectionOnViewWillAppear property which does it for you. And it defaults to true.
Not an ideal solution, but this works for me...
Table View Controller code changes:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tableView.reloadData() //added this
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "appCell") as! AppTableViewCell
cell.app = apps[indexPath.row]
cell.delegate = self
cell.reset() //added this
return cell
}
Table View Cell code changes:
//added this method
func reset() {
shortcutTypesTableView.reloadData()
}
Basically, I'm reloading the whole top table view, and in tableView(_:cellForRowAt:) I'm telling each cell to reset, which force's each cell's table view to also reload.
My app doesn't have much overhead when loading this table view (at least yet) so I don't notice a performance difference. However, I would not call this solution "ideal" for performance.
I have an UITableView that has multiple rows. The user is only allowed to select 1 row. I want to show the grey selection effect only while touching the row, not after the row is selected.
I set the selection effect to Grey in interface builder. This allows me to see the selection effect while touching, but it also shows the grey selection color after I made my selection. To fix this I tried the following code from https://stackoverflow.com/a/10402278/6414904:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = self.tableView.cellForRow(at: indexPath) as! AnswerTableViewCell
tableView.deselectRow(at: indexPath, animated: true)
}
This works partly. When I select a cell it only shows the Grey selection effect while touching the cell but after selecting a cell the grey selection effect is gone. This is what I want but with this code added it also allows the user to select multiple rows which I do not want. With this approach I also can't use the didDeselectRowAt method for other functionalities.
How do I create a selection effect which only shows during touch/hold but is removed after a selection while only allowing 1 row to be selected at all times?
For this specially one delegate method is available.
- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath {
// do something here
}
Add cell.setHighlighted(false, animated:true) to your didSelectRow call.
If I'm not mistaken, didSelectRow is only called after you release the button.
I have a tableview which is inside the a tableview cell.
After click the "JAVA" inside "test1", I click the "About" Row which don't have the tableview inside:
But you can see that, the "About" and "JAVA" have the background colour at the same time. This is the automatic feature of tableview in iOS, I don't know how to code to prevent this happen. What I want is that when I click the "Java" inside "test1", the background color of "About" would disappear.
You are going to need to keep track of which cell was selected if you only want one cell selected at a time from both table views.
The best way to do that is to create a delegate for the nested tableview. So when that cell is selected it can call back to the parent tableview and let it know to unselect anything that was selected. The main class will need to keep track of the index that was selected as if another one is chosen then it can reach into the cell with selected cell and deselect that.
A little tricky, are you sure you can't get the same results from just using one tableview and multiple sections?
Use this code it helps you
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var selectedCell:UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
selectedCell.contentView.backgroundColor = UIColor.greyColor()
}
To deselect the selected row use this code
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
var cellToDeSelect:UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
cellToDeSelect.contentView.backgroundColor = colorForCellUnselected
}
I have a TableView with 4 static cells, and each cell has a disclosure indicator. The disclosure indicator should fire a segue. This works fine, but only for the first cell. I cannot figure out how to wire up a segue for anything but the first cell, either programmatically or via the story board.
You can use the UITableView delegate like this:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// row 1 corresponds to the second cell.
if indexPath.row == 1 {
performSegueWithIdentifier("MySegueID", sender: self)
}
}
In the storyboard, create the segue from the first view controller (not from the cell itself) to the second view controller, and set its identifier to MySegueID``.
I have a Tab Bar Controller setup. When the user selects a tab, it takes them to a UIViewController. Currently I have a UITableView setup in this View Controller. What I would like to do is, upon selecting a cell from TableView1, I'd like to have a "push" effect where TableView2 comes in from the right side of the screen, and take over.
I've found the following question, similar to mine:
UITableView segue within the same ViewController
One of the suggestion is exactly what I want to achieve, however I could not get it to have that slide effect.
What I've done is added two UITableViews, then tableView1.hidden = true in viewDidLoad.
Then in code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell: UITableViewCell!
if tableView == tableView1
{
// Dequeue the cell to load data
cell = tableView.dequeueReusableCellWithIdentifier("ID1", forIndexPath: indexPath)
....
}
else if tableView == tableView2
{
// Dequeue the cell to load data
cell = tableView.dequeueReusableCellWithIdentifier("ID2", forIndexPath: indexPath)
....
}
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
if tableView == tableView1
{
tableView2.hidden = false
tableView1.hidden = true
playlistVideosTableView.reloadData()
// Deselects the row
tableView1.deselectRowAtIndexPath(indexPath, animated: true)
}
}
However, it doesn't have that "slide effect" and makes the tableview appears instant.
I could make another UIViewController with the second tableview but I don't want to make my Tab Bar disappear.
How can I achieve this, and how can I ensure the ensure gets back to the first UITableView?
Thanks
I would recommend to simply create another UIViewController that has a UITableView, so preferably a UITableViewController.
Then in tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) you call a segue to the new ViewController. This will give you the desired effect and is a cleaner solution as well.
You will not lose your TabBar either with this solution if you embed all ViewControllers in this tab into a NavigationController.
EDIT: sample code
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("editSpecialStage", sender: tableView.cellForRowAtIndexPath(indexPath))
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let indexPath = self.tableView.indexPathForCell(sender as! UITableViewCell)!
let secondViewController = segue.destinationViewController as! SecondViewController
}
And in the Storyboard you have a NavigationController as the first ViewController from the TabBar. Then the first ViewController and then the second, connected via push segue.
I could make another UIViewController with the second tableview but I don't want to make my Tab Bar disappear.
Why will your tab bar disappear? It wouldn't if you used a UINavigationController!
Just do what I say, alright?
First create that new view controller and connect the two VCs with a show segue
First VC -show-> Second VC
Now the whole picture would look like
Tab Bar VC -view controllers-> First VC -show-> Second VC
Now modify this to
Tab Bar VC -view controllers-> Navigation Controller -root vc-> First VC -show-> Second VC
Now the segue will slide the Second VC to the left and your tab bar won't disappear!