1

I am trying to get the specific row (in a TableViewController) in which the textField that was just edited is located (I have a TableViewController with a custom tableViewCell that has two text fields in it)enter image description here, so I could save the textField input to that corresponding index in my array, and then to Realm. I tried using a textField.tag as shown below in my code, however this had led to errors. Thank you so much, any help would be much appreciated!:)

  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> NotecardTableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "NotecardCell", for: indexPath) as! NotecardTableViewCell
    cell.termTextField.delegate = self
    cell.defTextField.delegate = self
    
    cell.termTextField.accessibilityIdentifier = "termTextField"
    cell.defTextField.accessibilityIdentifier = "defTextField"
    
    cell.termTextField.tag = indexPath.row
    
    cell.termTextField.text = noteCards?[indexPath.row].term

    return cell
}




func textFieldDidEndEditing(_ textField: UITextField) {
        do {
            try! realm.write {
                if textField.accessibilityIdentifier == "termTextField"{
                    noteCards?[textField.tag].term = textField.text ?? "default"
                }
            }
        }
    }
  • You are taking the right approach to the extent that you are giving a name to each text field with its accessibilityIdentifier property. However, you must give them an identity based on their row. – El Tomato Jul 01 '20 at 00:44

1 Answers1

0

You should implement the UITextFieldDelegate method in the cell. You can then use a closure or delegate to pass the event back to your table view controller.

For example, using a closure:


Enum TextFieldIdentifier {
    case term
    case definition
}

class NotecardTableViewCell: UITableViewCell, UITextFieldDelegate {

   var termTextField: UITextField!
   var defTextField: UITextField!

   var updateHandler: ((TextFieldIdentifier,String?)->Void)?

   func textFieldDidEndEditing(_ textField: UITextField) {
        switch textField {
            case termTextField:
                updateHandler?(.term,textField.text
            case defTextField:
                updateHandler?(.definition,textField.text)
            default
                break
        }
    }

Then, in your cellForRow:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> NotecardTableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "NotecardCell", for: indexPath) as! NotecardTableViewCell

    cell.updateHandler= { [weak self], (fieldType,content) in
        guard let self = self else {
            return
        }

        switch fieldType {
            case .term:
               do {
                   try realm.write {
                       noteCards?[indexPath.row].term = content ?? "default"
                   }
               } catch {
                   print(error)             
               }
            }
            case .definition:
                break
        }
         
    }
    
    cell.termTextField.text = noteCards?[indexPath.row].term

    return cell
}

Since the closure captures indexPath.row you don't need to do anything tricky to determine which row you are dealing with.

You could also use a delegation pattern. I show that approach in this answer (It is for handling a button tap, but the basic idea is the same).

Paulw11
  • 108,386
  • 14
  • 159
  • 186