Swift - Clicked button inside tableview cell does not call the did select row at function of that cell - swift

I creating a tableview programatically and each tableview cell have buttons associated to them.
If I click the row I can work out the tag associated with the buttons on that row and then able to edit the title when applying some other functions.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
TmpActionConnectorTag = indexPath.row + 700 //Tag associated to button
}
When the button is clicked , I have this code which changes the other button on that row
let tag = TmpActionConnectorTag
let tmpButton = self.view.viewWithTag(tag) as? UIButton
The issue is if I directly click on the button in the tableview cell, the did select row does not get call and no tag value is given. To do it I have to click within the cell first and then the button to be able to know the tag associated with the row.
Is there a way to workout the index row when the button is clicked so I don't have to click the actual cell?
above is how the cell looks normally and below shows how the cell has to be selected to be able to get the index value.

Button action won't call the didSelectRowAt. You should go for delegate method. If not aware about delegate means refer this

The cell's button will not trigger func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) instead you need to add a target to your button which is typically done within cellForItemAt.
Add target to button within cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = MyTableViewCell()
cell.button.tag = indexPath.row
cell.button.addTarget(self, action: #selector(didTapCellButton(sender:)), for: .touchUpInside)
}
Handle button action
#objc func didTapCellButton(sender: UIButton) {
guard viewModels.indices.contains(sender.tag) else { return } // check element exist in tableview datasource
//Configure selected button or update model
}

Disabling the button's control worked for me.
Programmatically:
editButton.isEnabled = false
~OR~
IB:
Uncheck the Enabled box in the Control section.

Related

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
}

I have a UItableView cell with a Image but can't get a image click to allow parameters

I have a EDIT2 UItableView, in Swift, with the normal labels and relevant Information. I have added a Image to the cell and all is working except when I click on the image I would like to open another ViewController with that particular cells relevant information. I have used:
let popup: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.popupalrmcontrnt))
cell.alrmwarning.addGestureRecognizer(popup);
as the means for calling the pushViewController function, But the Viewcontoller requires a parameter AlarmID to be set Beforehand. Said Viewcontroller needs AlarmID to fetch its relevant information.
Edit1 The parameter is dependant on the selected cell.
Create a closure variable in cell:
class SomeCell: UITableViewCell {
var imageClicked: (() -> Void)?
}
then in action of your tap gesture self.popupalrmcontrnt
add this line
func popupalrmcontrnt() {
self.imageClicked?()
}
then in your cellForRow, you can access this as:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
(cell as? SomeCell)?.imageClicked = {
//Navigate to your view controller here
}
return cell
}
Hope it helps!!
Better use UIButton. you can set image to the button as background image. Also you can pass relevant info as an object to the new ViewController.

How to save the state of UITableViewCell accessory checkmark in Swift 3

I have a table view and I would like the user to select only one item from the table view, then I want to add a checkmark to the cell. At the same time, I also want the checkmark on other cells to disappear so the. user can only select one at a time. Then I want to save the data (preferably using UserDefaults). How do I do that?
Create a class variable of type IndexPath. In your cellForRowAt method set .checkmark accessory type only if index path matches the class variable and .none otherwise. In didSelectRowAt method update the indexPath of selected variable and just reload the tableview
you should Use in this way
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let sgp : UITableViewCell = tableView.cellForRow(at: indexPath)!
sgp.accessoryType = .checkmark
}

Show image in cell when click and hide image in other cell Swift IOS

First i hide all images in cell. After i click on did select row, in that cell will show image and click again it will hide image. That working. But the problem is when i click on that cell (without click again) and then click other cell, (other cell will show image) but the previous cell will not hide image.
This code for cell and didselectrow
take one variable who contains current show image's indexPath.row value
var showImageIndex : Int?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let tableCell = tableView.dequeueReusableCellWithIdentifier("cellName") as? CustomCell
if showImageIndex == indexPath.row{
tableCell.IBimageView.isHidden = false
}else{
tableCell.IBimageView.isHidden = true
}
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
showImageIndex = indexPath.row
self.tableViewName.reload()
}
In your didSelect method before make anything with your index you need to hidden image in old cell.
this will hide image in your old cell
if(index != nil){
tableView.cellForRow(at:index!) as! FailOrderNoteTableViewCell
cell.rightViewCell.hidden = true
}
And other problem in your code is that you need to set nil for index if you haven't selected cell not row 99 and section 99 that will work fine

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?