0

I have a custom UITableViewCell Class.

The cell has editable UITextField. when this textfield is edited I trap the end of edit inside

func textFieldDidEndEditing(_ textField: UITextField)

my custom cell class implements UITextFieldDelegate so I do indeed get the call back.

Similar to all the other responses to similar questions - I first tried to just set the tag on the UITextField to the row number when loading the table.

This works - BUT - now there is a wrinkle .... My table allows the rows to be moved. When the row is moved it retains the tag from when the table was loaded so not my tags are all off from the insert on down. I could solve this by reloading the table after a move - but that jumps the list back to the top.

1) is there a cleaner way to get the row number inside the custom cell class without using .tag? because this fails when I allow rows to be moved.

2) if no to #1 then is there a way to go ahead and reload the display for first grab the current top displayed row and then after table reload reset to the same top current row so the users does not jump back to the top?

I also tried to just use this

  func tableView(_ tableView: UITableView, didEndEditingRowAt indexPath: IndexPath?)

and trap the end of editing inside the UIViewController that contains the UITableView so I would have the row number after the edit BUT this never gets called. so the other way to solve this might be to force didEndEditingRowAt to get called. For some reason this wont get called. even if I tuck in to the customer cell class the request to force end of editing

var textFieldHandle : UITextField?
func textFieldDidBeginEditing(_ textField: UITextField) {
    print("editing field in cell")
    textFieldHandle = textField
}

func textFieldDidEndEditing(_ textField: UITextField) {
    print("done editing text field in cell with text -\(textField.text!)-")
    if textFieldHandle != nil {
        textFieldHandle?.endEditing(true)   // force end editing so get table event - does not work
        if let index = textFieldHandle?.tag {
            if index >= 0 && index < quizListItems.count {
                // if we have a proper index then store back in answer array so we dont lose it
                quizListItems[index].text = textField.text!
                print("--set value at index \(index)")

            }
        }

    }

}
john
  • 505
  • 1
  • 7
  • 15
  • in your cellForRowAtIndexPath, did you set the delegate for your textFields? Another thought--> http://stackoverflow.com/a/22063354/4475605 – Adrian Jan 15 '17 at 02:13
  • hmmm.. I put the table delegate in the **ViewDidLoad** for the ViewController. I put the TextField delegates in the **override init(** of the custom Cell class. Should I NOT have the TextField delegate in the custom cell class and instead have the ViewController have theTextFiled delegate (and implement UITextFieldDelegate in VC)? For the reference to 4475605 can you elaborate? I need to know when edit of cell is done so I can update the data array that the table is loaded from with the new value of the textFiled **didSelectRowAtIndexPath** (i don't think) is called after editing is done – john Jan 15 '17 at 03:13
  • Update the tags of the `UITextField` on moving the textField? Use `moveRowAtIndexPath` delegate and update tags of the `UITextField` present in the 2 `indexPaths`. – Rikh Jan 15 '17 at 04:10
  • In 'moveRowAt' method I only have access to the cell for the newly inserted row. Yes, I could change the tag for this row, but after the insert all the rest of the .tag s below the insert will be off. I would need to reset all the .tag s. Ideally I could just know what cell I'm in. I tired to use 'didSelectRowAt' BUT the UITextField is eating the click so I never get call to 'didSelectRowAt' unless I find a thin space away from the UITextField. 'didSelectRowAt' should get called if I touch the UITextField as I an in the cell !!! BUT is does not. frustrating. – john Jan 15 '17 at 05:49
  • Using tags is bad, for the reason you have found. I suggest using a delegate and processing the field in your view controller (which is where this code probably belongs). See my answer here - http://stackoverflow.com/questions/28659845/swift-how-to-get-the-indexpath-row-when-a-button-in-a-cell-is-tapped/38941510#38941510 you can adapt it for your needs – Paulw11 Jan 15 '17 at 07:51

1 Answers1

0

I did this ....

func textFieldDidEndEditing(_ textField: UITextField) {
    let cell: UITableViewCell = textField.superview as! UITableViewCell
    let textFieldIndexPath = tableView.indexPath(for: cell)
    if let index = textFieldIndexPath?.row {
        if index >= 0 && index < quizListItems.count {
            // Stuff the input textField value in to the array that loads the table
            quizListItems[index].text = textField.text!
        }
    }
}

Note: the UITextFieldDelegate is on my ViewController (that contains the UITableView) and not on my custom UITableViewCell class

what else failed --- Tried using didSelectRow and didDeselectRow - BUT these never get called because the UITextField eats the click. In combo with didSelect path I tried to disable or make the UITextField not accept user action until i click in to the field. This was a mess. for some reason there are errors trying to get the cell inside of didSelect and didDeselect. Took that back out and

what worked (the code snip above) --- went back to the UITextField delegate method for textFieldDidEndEditing and worked backwards to the cell to get the index. This works and still works even in I move a row.

This path gets from the UITextField back to the cell then fro the cell get the index.

john
  • 505
  • 1
  • 7
  • 15