didSelectCellAtIndexPath not called - swift

I know there are a lot of relevant post on this and I have tried all of the ones I can find and unfortunately the problem still persists.
So I have a tableView inside of an UIViewController which is populated by 2 custom cells, one has got an UITextField and the other one got an UISwitch, and both have a UILabel. I then proceeded to implement the didSelectCell(at: IndexPath) method
I made sure the delegate is hooked up to the view controller.
Inside of the method, I simply wrote a print statement to ensure the taps are registering. However, the print message did to get printed to the console when I tapped on the UITextField and on the UILabel.
I have a feeling it is something to do with the firstResponder thing with the UITextField, and it is eating away my tap registration, but not really sure.
Any feedbacks are welcome!
UPDATE
Here is the setup on my custom cell:
Here is the didSelect method:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("tapped on cell")
if let cell = tableView.cellForRow(at: indexPath) as? NumericInputTableViewCell{
print("Tapped on numericcell")
} else if let cell = tableView.cellForRow(at: indexPath) as? BooleanInputTableViewCell {
print("Tapped on booleancell")
}
}

The delegate method is triggered when you click on the cell, not other elements on the cell. So create some empty cell in your table view and have another try. If it get printed out then that means you have elements covered over the cell and the cell itself is not clicked.
You can then disable user interaction for your UITextField stuffs from storyboard and then have a try. Ideally, when you click on the textfield on a table view cell, the correct respond I am thinking is that keyboard will show up and didSelectCell should not be triggered.
Here is the demo

Related

How to transfer data from one tableViewCell to another tableViewCell in swift

How i can transfer data from cell of tableView to cell of another tableView. I am confused about it. I can try delegate method,closure but they doesn't work on it. I want to show data of cell to cell of another tableView by single click on button. So please help me.
I try closure and delegate method to transfer data .but it doesn't work.Actually i am confused in tableView didSelectRowat function. It deal with cell on which i tapped and next step is when i tap on button this cell data shown on another cell which has different tableView & different viewController.
Assuming first tableviewcontroller is called "ItemsViewController"
and your second view controller is called "DetailViewController"
in your ItemsViewController add this to your didSelectRowAt delegate function:
then you can send that cells information to the next view according to it's IndexPath
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let vc = storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as? DetailViewController {
vc.image = UIImage(named: images[indexPath.row])
vc.name = names[indexPath.row]
navigationController?.pushViewController(vc, animated: true)
}
}

How to get didselectrowat from a custom cell with textboxes?

I have a dynamic tableview with 3(cell1,cell2,cell3) custom cells, which gets reused anywhere from 0 times up to 9 times. (Maximum cells in the tableview will be 27 cells).
Each of those 3 custom cells have 3 text boxes each, and in addition the second cell has 2 buttons to select gender and 3rd custom cell has a drop down menu, which has values of whatever typed in the first textbox of cell1 cells.
Now the issue is that, textbox takes the touch input from user (as it should) and didselectrowat never gets called and therefore i am not getting indexPath.
But i need the indexPath, so that i can insert user details from each of those cells into an array.
(anArray.insert("", at: indexPath)
Since i am not getting indexPath, everything fails. How can i get the indexPath and get the touch on to the textbox?
I am thinking of something like a function that takes the touch ,gets the indexPath and then passes the control to textbox.
Things i have tried.
I disabled the textboxes before user touches the cell (and makes textboxes disabled once user deselects the cell, so cell takes the touch. Once didselectrowat gets called, make the textbox active again and make
textbox.becomeFirstResponder()
But somehow , the textbox never becomes the first responder even though breakpoint shows the control going through it and the textbox becomes active. But no keyboard popsup, if i touch the cell again, same process happens.
What seems to be the issue here? I saw another post on the same topic, i tried it but unfortunately that doesnt work and it was for a static tableview.
Also is there a good way to do this? Other than making the user click on the cell twice / clicking outside the textbox..
You can set your custom cell as delegate for UITextField and use a callback for editing begins/ends as below,
class MyCustomCell: UITableViewCell, UITextFieldDelegate {
public var editCallback: (() -> Void)?
/// Set 'textField.delegate = self' on initialization.
func textFieldDidBeginEditing(_ textField: UITextField) {
self.editCallback?()
}
}
And use the callback in cellForRowAt as,
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = MyCustomCell()
cell.editCallback = { [weak self] in
print(indexPath)
}
return cell
}
you can try this
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
//your code here
}

How to enable User Interaction on Disclosure Indicator, but not on UITableViewCell

I have a UITableView with Static cells. I want some off the cells to have a disclosure indicator that segues to another view.
The issue is that if the user inadvertently clicks the body of the cell, rather than the disclosure indicator, the cell changes color (grey), and remains so.
Is it possible to disable user interaction on the cell but not the disclosure?
override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
let identifier = tableView.cellForRow(at: indexPath)?.reuseIdentifier as! String
selectedCellIdentifier = identifier
switch identifier {
case "DescriptionCell":
performSegue(withIdentifier: "ShowHelpView", sender: indexPath)
...
}
I can't call tableView.didDeselect because if the user successfully clicks the next disclosure, the first cell remains selected (grey color).
Change the selection type of the cell to None in the xib or storyboard. Or in the cellForRowAt: you can set it to .none. This will prevent the grey selection state.
If you do not implement the didSelectRow delegate method then there will be no interaction for the cell.
You could just set cell.selectionStyle = .none in cellForRow:At:.

Swift DidSelectRowAt not firing

I have a project with a few different VCs...two of them have TableViews
The first one works perfectly fine, I have a custom view in there etc.
The second one is also custom and it fill the information in just fine, but unlike the first one...I cannot tap on it to segue to the next VC
I have the Delegate and DataSource set up properly. I have another VC on my project with a tableview and it works just fine. The first thing I can think might be preventing it from working is a UILabel takes up 90% of the cell, but I don't think that is it because I made the label small and tried tapping then and it still wouldn't hit the breakpoint.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let row = indexPath.row
selectedService = serviceArray[row].serviceID! as String
if selectedService != "" {
self.performSegue(withIdentifier: "fromCardDetailsToEditService", sender: self)
}
}
I do not know if it matters BUT...the VC that I am on is in a Tab Bar Controller and a Nav Bar Controller. Does it matter for the performSegue that I am in a Tab Bar? And that this button is not a tab bar item?
Did you have any GestureRecognizer on your UIViewController because in case of GestureRecognizer tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) does not called.
I figured out how to have my Gesture Recognizer AND the didSelectRowAt.
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(CardDetailsViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
This is what I already had, which was causing conflict.
To fix it, this simple line let me dismiss the keyboard AND be able to tap on my cells.
tap.cancelsTouchesInView = false

How to add a subview to a UITableViewCell

I'm making a to-do planner using a table view. When the user presses enter after typing in a task, a button should appear to the left of the task.
The textFieldShouldReturn method in my ViewController class adds the button but not always in the top left corner of the screen. I have it set up like this:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")! as! TextInputTableViewCell
self.view.addSubview(cell.cellButton) // puts a button in a wrong location, button doesn't respond to any action
cell.addSubview(cell.cellButton)
tableViewData.append(textField.text!)
lastItem = tableViewData.count
print(tableViewData)
print(lastItem)
self.tableView.reloadData() //update row count and array count
textField.resignFirstResponder()
return true
}
self.view.addSubview(cell.cellButton)
adds a button to the view but the button doesn't appear in the right place, (i tried moving the location using storyboard, but it doesn't do anything). Plus the button doesn't respond to its appropriate click action, which is declared in the subclass.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell")! as! TextInputTableViewCell
cell.textField.delegate = self
...
return cell
}
Any help is appreciated. Let me know if I am not too clear
You're not grabbing the right cell in this line:
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")! as! TextInputTableViewCell
You're basically telling the system to just give you a cell. You need to figure out what text field actually returned, and grabbing the cell that contains that text field and then adding your subview to the right cell. The way todo this would be to tag your textFields with the row number.
It works in the first example because you are in cellForRow, so you do have the right cell.
Would it be easier if you aligned the button in your .xib or storyboard file, and then kept it hidden until you needed it to appear?