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.
Related
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)
}
how can i respond to cell taps in static tableview? Is there a way to link it with code? I know that i can use a dynamic one but isn't it possible with a static one?
didSelectRowAt doesn't get called
Code for Selecting not working
class SettingsVC: UITableViewController, UITabBarControllerDelegate {
// MARK: - View lifecycle
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("SELECTED") // not get called
}
}
This can be done using a Static table in a UIContainerView.
Here is the Storyboard setup:
and how it looks at run-time:
When you use a UIContainerView it creates an embed segue... and that will trigger a prepare call where you can set the tableView's delegate to self (if desired).
Here's the code:
import UIKit
class EmbedTestViewController: UIViewController, UITableViewDelegate {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// When using UIContainerView, prepare for segue will be called on load
// un-comment this block to use SELF as the delegate
// for the tableView in the embedded tableViewController
//if let vc = segue.destination as? MyStaticTableViewController {
// vc.tableView.delegate = self
//}
}
// this will only be called if .delegate is set as shown above
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("didSelectRowAt called in \"Parent\" for indexPath:", indexPath)
}
}
class MyStaticTableViewController: UITableViewController {
// this will NOT be called if .delegate is set as the "parent" view controller
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("didSelectRowAt called in \"Table View Controller\" for indexPath:", indexPath)
}
}
Note the comments and commented lines of code in the prepare func in EmbedTestViewController.
If you run this with those lines commented, didSelectRowAt will be called in MyStaticTableViewController class.
If you un-comment those lines, didSelectRowAt will be called in EmbedTestViewController class.
EDIT
Here is a full example: https://github.com/DonMag/ContainerTableView
You need to either:
Change SettingsVC to be a subclass of UITableViewController.
Make SettingsVC the delegate of your table view, since tableView(_:didSelectRowAt:) is a method of UITableViewDelegate.
This question seems to have been asked many times on StackOverflow, but after searching for hours, I still haven't found the solution to my issue.
I have a table view in SecondViewController.swift and I did make it delegate and dataSource SecondViewController.swift, but the didSelectRowAt method is still not fired when a table cell is clicked. I am trying to apply a segue to another view controller, but the didSelectRowAt method isn't working itself.
I have selected Single Selection in my storyboard in the table view properties, and I have made sure that user interaction is enabled for the table view and the prototype cell.
For the SecondViewController.swift below, please assume that allEvents are populated into the allEvents array. I was able to successfully populate them and display them in the table. The only problem is clicking on the row to perform a segue. Also, please ignore the awkward indentation below.
SecondViewController.swift
import UIKit
class SecondViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
var allEvents: Array<JSON> = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
//self.tabBarItem.image = myTabImage
self.tabBarController?.tabBar.isTranslucent = false
self.tabBarController?.tabBar.barTintColor = UIColor(red:0.25, green:0.25, blue:0.25, alpha:1.0)
self.tabBarController?.tabBar.tintColor = UIColor.white
//ASSUME ALL EVENTS ARE POPULATED INTO allEvents
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: Tableview Datasource
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return allEvents.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 150
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("SEGUE")
self.performSegue(withIdentifier: "oneSegue", sender: allEvents[indexPath.row])
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "eventViewTableCell", for: indexPath) as! EventViewTableCell
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// let detailController = segue.destination as! EventDetailsController
}
}
I have been on this for hours and still have not found out the problem. I would greatly appreciate any help!
You may want to check your tableview again, do choose single selection.
I'm assuming you are selecting No Selection as the picture bellow
Hope it helps.
I had the same problem on a Controller within a TabBarController.
What fixed it for me was this:
Disable the User Interaction for the Content view
My guess is that it was becoming the responder so it removed the event from the TableView
Note: Since the viewDidLoad assignments to delegate and dataSource became redundant after setting it up in the StoryBoard, I removed them, although leaving them does no harm.
If you do nothing else than calling the segue in didSelectRowAt remove the entire method and connect the segue in Interface Builder to the table view cell (rather than to the controller). The sender parameter will contain the reference to the selected table view cell.
I suspect when you collected and populated your allEvents array did you collect any touch events in there ?
or have you used UIGestureRecognizer in this or it's super view ?
If you have intercepted any touch event to populate your array or any other purpose comment it out and test it with a simple preloaded array like :
let dataSource = ["1", "2", "3", "4"]
let me know if this is not your case so I can find another solution.
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)
}
New to IOS development and am having trouble with handling cell selection on a table. Whenever I select, the method is not getting called below - any idea why?
My project structure is:
View Controller -> View -> Table View
The below code demonstrates the method calls. The others get called no problem! I know touch is working as pull down successfully refreshes and on clicking a cell it does become highlighted.
import UIKit
class ViewController: UIViewController, UITableViewDelegate
{
let blah = ["blah1"]
//How many sections are in the table?
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
//How many rows? (returns and int)
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return blah.count
}
//table contents for each cell?
//Each time this is called it'll return the next row and thus build a table...
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("Populating each cell of table view!\n")
tableView.rowHeight = 80.0
var cell = UITableViewCell()
var(a) = blah[indexPath.row]
var image : UIImage = UIImage(named: a)!
cell.imageView.image = image
return cell
}
//Code Cell Selected
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
println("You selected cell #\(indexPath.row)!")
}
func tableView(tableView: UITableViewDelegate, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
print("wananananaanan" )
println("You deselected cell #\(indexPath.row)!")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Everybody is mentioning to set dataSource and delegate of the tableView.
But after setting also not working fine then sometimes it may happen because of none or disable selection of table view.
To enable it
Go to storyboard -> Select tableView -> click on the attribute inspector ->go to selector -> Select selection as single selection (or multiple selection according to the requirements.)
Please find attached screenshot for your suitability.
You have to set an #IBOutlet to the tableView in you ViewController and set as it's delegate and dataSource to you can see the data an respond to changes in the tableView.
Something like this :
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
}
And implements the UITableViewDataSource protocol too.
Or you can too in the Interface Builder set the ViewController as it's delegate and dataSource (more easy to do I think) and avoid to set manually in code like above. Is up to you.
I hope this help you.
SWIFT 3
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Do here
}
Use the above delegate method in swift 3
Couple of checks that can help you:-
myTableView.allowsSelection = true
myTableView.delegate = self
Make sure you written didSelectRowAt correctly:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
If you are using UIButton on UITableViewCell then it overlaps cell so check Solution here
I faced the same issue when compared two identical code examples where one was working well and the other was not calling didSelectRowAtIndexPath
Take a look at two possible ways to solve the issue:
1) In the code itself:
#IBOutlet weak var table: UITableView!
override func viewDidLoad() {
table.delegate = self
table.dataSource = self
//data source might be already set if you see contents of the cells
//the main trick is to set delegate
}
2) Using Storyboard or Document Outline (which was the problem in my case cause storyboard changes are not visible in .swift controller classes.
Open Document Outline and Control + Press your TableView
you will see two outlets called "delegate" and "dataSource"
drag them 1 by 1 to the containing ViewController (right onto the yellow circle)
That's it!
Another caveat is tap gesture recognizers. It's a common use case to use tap gesture recognizer to handle different logic within your view controllers with table views, whether that's exiting touch control or first responders.
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(viewTapped))
view.addGestureRecognizer(tapGesture)
E.G. This line of code handles dismissing a date picker in my application and prevents my tableview from calling didSelectRow delegate method
You have to use this: First take a look what are you extending and then use the tableView method.
class YourViewController : UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var mUITableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// We need to tell to UITableView that we will add the data by ourselves
self.mUITableView.delegate = self
self.mUITableView.dataSource = self
// Register the UITableViewCell class with the tableView
self.mUITableView?.registerClass(UITableViewCell.self, forCellReuseIdentifier: self.cellIdentifier)
// Setup table data
getEvents()
self.mUITableView.allowsSelection = true
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
// here to create you cell view
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("You selected cell #\(indexPath.row)!")
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "subtitleCell")
cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
cell.textLabel?.text = "\(tableData[indexPath.row].name) - (\(tableData[indexPath.row].eventStateId))"
cell.detailTextLabel?.text = tableData[indexPath.row].lastUpdate
return cell
}
}
Another reason you may write this function which allowed to click under condition
func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
if(indexPath.section == 1){
return true
}
return false
}
Another caveat which took me ages to figure out is to make sure that all three of your Table View, your Cell and your Content View all have User Interaction Enabled. Then in Swift 4, at least, you can use:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
if you are editing your tableView:
tableView.allowsSelectionDuringEditing = true
Another thing to check is the access level for your class & method:
I had a Swift UIViewController class marked #objc public, to make it visible to my objective-c code.
In this context you must add public access to this function, or it will not be called.
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
Nothing happened till I've cleaned and built again. :)