Swift leave a row selected after changing viewcontroller - swift

i have a two view application. If i select a row a segue load the second view Controller. I want that when i return back to my first controller the row is is still selected. I have tried with this:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)!
self.tableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: UITableViewScrollPosition.None)
}
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
but when returning back the row not remain selected. What's is the problem??
P.S.: I want no multiple selection, only one row at time.

If you are using a UITableViewController subclass as your source view controller, what I presume because you are overriding the table view delegate methods, you can use the flag clearsSelectionOnViewWillAppear on your view controller to get this behavior.
override func viewDidLoad() {
self.clearsSelectionOnViewWillAppear = false
}
Or you can set this in your Storyboard as well, when selecting the attributes selector of your source table view controller, you have to untick the Clear on Appearance checkbox.

Related

Swift segue negating other functions connected to segue object

In a table view controller, I'm trying to get the index of the row that is selected before I segue (will pass this info in prepare for segue eventually). I have implemented this function:
var selectedQuestionCell: IndexPath?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedQuestionCell = indexPath
}
This was working great for me initially. I was able to snag the index of the selected row in my table. However, I want to perform a segue when a row is tapped which will transfer to another View. I connected a segue to my cell (dynamic prototypes). After connecting a segue, my override function no longer executes! I'm really new to Table View Controllers, so I'm not sure if there's anyway I can manually execute this.
To summarize: my problem is after connecting a segue to my cells, the override function to get their index is no longer called. How can I fix this?
Try these thing
Create a new segue from your tableview to another view and name it as you like.
Now add this code inside your didSelectRowAt
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let viewController = storyboard?.instantiateViewController(withIdentifier: "your_segue_name_here") as! YourViewControllerName
self.navigationController?.pushViewController(viewController, animated: true)
}
Please make sure that your tableview is connected with navigation controller.
To do that select your tableView then click on Editor -> Embed In -> Navigation Controller from your Xcode.
I hope it works for you.
: D

Table View Cell Stays Highlighted No Matter What

My storyboard-based UITableViewController subclass pushes another view controller into the navigation when the user taps one of the table view cells.
I am using a segue to accomplish this, and not doing it programmatically with pushViewController(:animated:).
The problem I'm having is that my table view cell stays highlighted (light gray) all along, even after popping the view controller (again, with an 'unwind' segue). The only way to clear it is to call tableView.reloadData().
I have tried:
Setting:
self.clearsSelectionOnViewWillAppear = true
in viewDidLoad() (Should not be necessary, since it's already the default: The template code has self.clearsSelectionOnViewWillAppear = false commented out, and suggests to uncomment it to override the default functionality).
Also:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let indexPath = tableView.indexPathForSelectedRow {
tableView.deselectRow(at: indexPath, animated: true)
}
}
...to no avail.
EDIT: Turns out viewDidAppear() is not called on navigation pop, only after being added to the view hierarchy (e.g., addSubview()). Placing this code in viewWillAppear() does the trick. But my question at the end of this post still stands.
I have also tried implementing this method:
override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
...but it is not being called (perhaps because of the segue?)
The only thing that successfully unhighlights the cell is calling:
tableView.deselectRow(at: indexPath, animated: true)
...from within prepareForSegue(). But that happens on push, and I want to de-highlight my cell on pop.
Do I need to setup a dedicated unwind method for the push (cell tap) segue, and unhighlight there?
Why doesn't it work out-of-the-box, even though I am subclassing UITableViewController?
Like what you mention, using tableView.deselectRow(at: indexPath, animated: true)
However, instead of having it in:
override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
You should be putting it in:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// You other cell selected functions here ...
// then add the below at the end of it.
tableView.deselectRow(at: indexPath, animated: true)
}
didDeselectRowAt will not be called until a row is deselected. So in order to de-select the cell, you should be adding it in the didSelectRow. This way whenever a cell is selected and didSelectRow get trigger, you will run your other code and also de-select the cell at the end of it.
The third option should work, I think you just accidentally autocompleted with didDeselectRow, not didSelectRow.

Swift: How to enter edit mode for table?

I have a RootViewController that embeds a container that contains a table:
I'd like the garbage can icon on the top left of the RootViewController to enable editing mode for the embedded table view. I would like them to show up as checkboxes so that I can select multiple rows at once and then press "Delete" to delete all of the selected ones.
How would I do this?
Hopefully your class already conforms to UITableViewDelegate like so:
class MyViewController: UIViewController, UITableViewDelegate
In viewDidLoad(), you would need to have:
myTable.delegate = self
Then you can hook up the trash can icon to an IBAction that sets the table to editing mode:
#IBAction func myTableSetEditing(sender: AnyObject) {
myTable.setEditing(true, animated: true)
}
Then, as we see in an answer here: Select multiple rows in tableview and tick the selected ones, in viewDidLoad() put:
self.tableView.allowsMultipleSelection = true
and to get your checkmark, implement:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = UITableViewCellAccessoryType.Checkmark
}
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = UITableViewCellAccessoryType.None
}

Why can't I select TableView cells?

This is the flow of my app:
First, the TableView is set to hidden. There is a UITextField in the center of the screen. When the user types something and hits Go, this code is run:
self.view.layoutIfNeeded()
UIView.animateWithDuration(0.5, animations: {
self.textFieldConstraint.constant = -230
self.tableView.hidden = false
self.goButton.hidden = true
self.view.layoutIfNeeded()
}, completion: nil)
At this point, the tableview is populated. When a row is selected, I need to manipulate the data that is populating it.
However, absolutely nothing happens when I tap a cell.
What am I doing wrong?
My TableView code is here:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: SearchResultsTableViewCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! SearchResultsTableViewCell
cell.label.text = searchResultsNames[indexPath.row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return searchResultsUrls.count
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("HELLO")
}
And, I have set the dataSource and delegate properly.
I also want to clarify that the tableView populates and scrolls properly; it just won't do anything when I tap a cell.
Update:
I've discovered that for some reason, I can select the cells when I press and hold them. It is not what I want, so does anybody know how to fix this?
I have just used your code to create a simple table, selection is working fine and logging out HELLO as expected. Can you check the values of Selection in the attributes inspector? Here is mine, which has Selection set to Single Selection.
And here is the code I used for my simple table
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var searchResults = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
searchResults.append("Testing 1")
searchResults.append("Testing 2")
searchResults.append("Testing 3")
searchResults.append("Testing 4")
searchResults.append("Testing 5")
tableView.dataSource = self
tableView.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("tableCell", forIndexPath: indexPath)
cell.textLabel?.text = searchResults[indexPath.row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return searchResults.count
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("HELLO")
}
}
I also tried hiding and showing the tableView which made no difference on selection.
EDIT & SOLUTION:
In the comments below, we discovered that the issue is related to a tapGestureRecogniser on the view, This was identified by the op only being able to make a selection by holding a tap on the cell. The gesture has to fail before the selection can be made, the op managed to solve the problem by referring to this other SO Answer
if you use "tap" gesture, you can't select table cell. (but, if you click and drag to right a cell, you can select it.)
Check gesture first.
And if your code has self.tableView.allowsSelection = false, replace false to true or delete this line.
My problem has been caused by the tap gesture recognizer on the view controller itself (I had BaseTableViewController I was extending from). Probably it was interfering with the gesture recognizers of UITableView.
In your viewDidLoad, or wherever you set up your view, make certain that your table view even allows selections. That can be controlled with the allowSelection property.
Something like:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.allowsSelection = true
}
If you have a gesture recognizer, just type gestureRecognizer.cancelsTouchesInView = false
For me I was implementing another did select row method, so I erased it and typed "didSelect..." and selected the first one in the suggested methods, which is this for swift 3:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Row #: \(indexPath)")
}
Try disabling and then enabling the user interaction Enabled property in the attribute inspector of your tableView
Looks something like this
I met the same problem as you and solved it by removing the below code
self.view.layoutIfNeeded()
you can try it.

How to send didSelectRowAtIndexPath back to view controller in swift

I have 1 viewController and 1 tableViewController in swift. I can send an NSMutableArray from the viewController to populate the tableViewController using segue. I do not know how to send the selected row back to the view controller. The code so far:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You selected cell #\(indexPath.row)!")
// Missing code for sending back the selected row
self.dismissViewControllerAnimated(true, completion: nil)
}
Any ideas?
You can use the delegation pattern. Create a protocol:
protocol MyDataDelegate {
didSelectRow(row: NSIndexPath, data: MyData)
}
In the table controller, add a property:
var myDataDelegate: MyDataDelegate?
and in the didSelectRowAtIndexPath call the delegate method:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You selected cell #\(indexPath.row)!")
let data = getDataForRow(indexPath) // <== You need to implement it
self.myDataDelegate?.didSelectRow(indexPath, data: data)
self.dismissViewControllerAnimated(true, completion: nil)
}
Next, in your main view controller:
implement the MyDataDelegate protocol
implement the MyDataDelegate.didSelectRow method
right before presenting the table controller (or after creating it, if you manually do it), set the myDataDelegate property of the table controller to self
This way, when a row is selected in your table controller, the didSelectRow method is called on your main view controller, so you can do whatever you need with the index path and/or the data.
Of course feel free to change the didSelectRow signature (use the indexpath, or a row index, with or without data, etc.)