UITableView reselects row when scrolling - ios

I've got a tableView with static cells. The modalCell (see screenshot) has a segue to a viewController that the tableViewController presents modally. If I dismiss the modal view, the cell gets deselected. However, when I scroll the cell out of the screen and scroll back so that it appears again, the cell is selected again. I reproduced this behavior in a fresh example project.
Here is my storyboard setup (nothing fancy):
My Code in ViewController looks like so:
class ViewController: UITableViewController {
#IBOutlet weak var modalCell: UITableViewCell!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath), cell == modalCell {
modalCell.setSelected(false, animated: true)
}
}
}
In the screen recording, you can see that the cell deselects correctly. However, if I scroll, the cell is selected again. Any ideas why?

Just deselect cell in table view
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}

Related

TableView Cell not loading View Controller until Different TableView Cell is clicked

I've searched around and haven't truly found why this is happening. Basically, I followed this tutorial https://www.youtube.com/watch?v=yupIw9FXUso by Jared Davison on creating Table View Cells to Multiple View controllers. In his example, everything works perfectly, but for some reason when you click on a table view cell in my code the cell is highlighted in grey. Then, when the user clicks on a separate table view cell the view controller that should have been loaded by the first table view cell is loaded. If the user then clicks back on the original table view cell the page that should have been loaded by the second table view cell is loaded. In summary, all of the view controllers are loaded a "click" behind.
Here is the code for the table view:
//Feed Navigation Functions
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return elements.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 75
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "feedCell") as! FeedTableViewCell
cell.txtTitle.text = "The Fight Against \(elements[indexPath.row])"
cell.issueIcon.image = UIImage(named: "Issue Icons_\(elements[indexPath.row])")
return cell
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let vcName = identities[indexPath.row]
let viewController = storyboard?.instantiateViewController(withIdentifier: vcName)
self.navigationController?.pushViewController(viewController!, animated: true)
}
Update: The array is a simple array of strings for example [One, Two, Three] there are 6 strings in the array.
When you select a cell then select another one the method didDeselectRow is called so the Vc is pushed you actually want to implement didSelectRowAt
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vcName = identities[indexPath.row]
let viewController = storyboard?.instantiateViewController(withIdentifier: vcName)
self.navigationController?.pushViewController(viewController!, animated: true)
// this to deSelect it after push
tableView.deselectRow(at: indexPath, animated: false)
}
This method fired when a cell is selected
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath
This method fired when a cell is deSelected
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath
You want to use the tableView's delegate method didSelectRow instead of didDeselectRow I think...
Issue: click on a table view cell in my code the cell is highlighted in grey
This is due to the selectionStyle, which you can read about here. If you don't want the cell highlighted, you can set cell.selectionStyle = .none.
Edit: As indicated in other correct response - issue was with incorrect/typo in method - we should use didSelectRowAt not didDeselectRowAt.

didSelectRowAtIndexPath not working in staticTableViewCells

hello I have a TableViewController in my storyboard with static cells. I want to launch different view controller or trigger some methods on each cell clicked. if I drag the segue from my cell to another ViewController it doesn't work and also didSelectRowAtIndexPath also not working.
here is my class
class ProfileTableViewController: UITableViewController {
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
let row = indexPath.row
print("Row: \(row)") //nothing is printing out
}
override func viewDidLoad() {
super.viewDidLoad()
print("hello")
}
}
If you are adding the TableView in Storyboard, make sure that when you right click the TableView, that the UIViewController which holds the TableView is set as its delegate, or any other object which seems proper for your task.

SWRevealViewController nib cell not performing segue

Simply put, I have a slide navigation view controller in my app with a back table VC and a front table VC. A selected cell in the back table VC is supposed to segue to the front table VC (embedded in a navigation VC). To illustrate, here are the isolated pre-change settings and code with it working properly:
Here is the simplified working code in my back table VC's cellForRowAtIndexPath method:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let navigationCell = tableView.dequeueReusableCellWithIdentifier("NavigationCell", forIndexPath: indexPath) as UITableViewCell
return navigationCell
}
Ok, onto the fun part. All I want is to replace the default UITableViewCell shown above with one of my custom cells in a Xib file. Now I'll illustrate what I modified. First, here's my Xib cell in my NavigationCell.xib file. Nothing special.
My NavigationCell class code is simply
import UIKit
class NavigationCell: UITableViewCell {
#IBOutlet var nameLabel: UILabel!
}
Finally, I modified my code in my back table VC to register the Xib and dequeue the custom cell:
override func viewDidLoad() {
super.viewDidLoad()
let navigationCellNib = UINib(nibName: "NavigationCell", bundle: nil)
tableView.registerNib(navigationCellNib, forCellReuseIdentifier: "NavigationCell")
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let navigationCell = tableView.dequeueReusableCellWithIdentifier("NavigationCell", forIndexPath: indexPath) as! NavigationCell
return navigationCell
}
All other code and specifications remain the same. The storyboard segue for the new custom cell is still from the class SWRevealViewControllerSeguePushController as shown in the first screenshot for this question. I simply swapped out the default UITableViewCell with my custom Xib cell.
This modification was enough to stop the segue from occurring. With this modification, after I build and run when I slide out the back table VC navigation menu and select one of my custom navigation cells (which display properly), it doesn't trigger any segue. Any thoughts?
I'm an idiot. I had to perform the segue programmatically in didSelectRowAtIndexPath.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("MySegue", sender: self)
}

Seconds of delay before triggering segue with custom table cell

I'm having this strange issue in my app where it sometimes takes several seconds (10ish) for a custom TableViewCell to trigger a segue to another ViewController. If I click anywhere else in the app during this time, the click triggers the segue.
The problem only occurs when selecting the same cell several times. Meaning if you click the first cell, segue over to the new ViewController, exit the new ViewController and click the same cell again, the problem could occur.
I've reconstructed this issue in a small project here for any kind souls to try out.
http://www.filedropper.com/customcellsegue_2
Any ideas guys?
Edit
Alright here's some code for you guys who don't wanna download the app.
Original ViewController
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 100.0
}
// Number of cells in each section.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
// Fill UITableView...
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("Selected")
}
Custom Table Cell
class customCell: UITableViewCell {
#IBOutlet var firstLabel: UILabel!
#IBOutlet var secondLabel: UILabel!
}
New ViewController
#IBAction func close(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
I've simply applied a modal segue from the custom cell to the new ViewController.

UIActivityIndicatorView (spinner) in UITableViewCell cannot start animating by UITableViewController in swift

I have a custom UITableViewCell containing a UIActivityIndicatorView (spinner), and I try to click on the cell so that spinner starting to animate. So I try to implement following in UITableViewController:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.dequeueReusableCellWithIdentifier("testcase", forIndexPath: indexPath) as TestCaseTableViewCell
cell.spinner.startAnimating()
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
I have the instance variable "spinner" in my TestCaseTableViewCell(custom cell class):
#IBOutlet weak var spinner: UIActivityIndicatorView!
But it didn't work......
I just want to click on the cell, and the spinner starts to animate cause I want to do something in this period. While the something is done, I can show something like "OK" in the cell(as the same position of the spinner). How can I achieve that?
The problem is with how you are retrieving your cell from the table view: dequeueReusableCellWithIdentifier(identifier: String, forIndexPath indexPath: NSIndexPath). This method asks the UITableView for a cell from its reuse cache when you need a new cell to display, so should only be used in the tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) method of your table view's data source.
To ask the table view for an on-screen cell, use cellForRowAtIndexPath(indexPath: NSIndexPath). Your code sample then becomes:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) as? TestCaseTableViewCell {
cell.spinner.startAnimating()
}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
Another simple method:
Select your UIActivityIndicatorView and check "Animating" in the attribute inspector
Check "hidden"
Now do this:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.dequeueReusableCellWithIdentifier("testcase", forIndexPath: indexPath) as TestCaseTableViewCell
cell.spinner.hidden = false // <== Here
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
Don't forget to hide the unhidden UIActivityIndicatorView if needed ;)

Resources