1

I am using a sectioned tableView in my app, each row of the tableView contains a textField, when textFieldDidBeginEditing I need to know the indexPath of that textField. Using the tag can only get the section or row, and creating an extension of UITextField doesn't allow you to add variables. How can I get this done?

Noah Iarrobino
  • 1,435
  • 1
  • 10
  • 31
  • If there are UITextFields within your UITableView cells then I believe your didSelect(:IndexPath) stub should be firing when the UITextField becomes first responder. Explore that first. If that doesn’t work, try to override the UITextField class with a Closure to execute on becoming first responder. – pinglock Sep 17 '20 at 03:27
  • 1
    You can subclass UITextField and add a indexPath property to it. https://www.dropbox.com/s/2yq641m7g5v6a7g/TableView%20with%20TextFields.zip?dl=1 – Leo Dabus Sep 17 '20 at 04:09
  • Possible duplicate of https://stackoverflow.com/questions/28659845/how-to-get-the-indexpath-row-when-a-element-is-activated – Martin R Sep 17 '20 at 05:02

5 Answers5

4

I like to walk from the text field to the cell and ask the table view for its index path.

extension UIResponder {
    func next<T:UIResponder>(ofType: T.Type) -> T? {
        let r = self.next
        if let r = r as? T ?? r?.next(ofType: T.self) {
            return r
        } else {
            return nil
        }
    }
}

And

func textFieldDidBeginEditing(_ textField: UITextField) {
    if let cell = textField.next(ofType: MyCell.self) {
        if let ip = self.tableView.indexPath(for:cell) {
           // whatever
        }
    }
}
matt
  • 515,959
  • 87
  • 875
  • 1,141
2

There are way to do it but it's bad design anyway, suggest you to put the textfield delegate inside the cell class.

You can try to get the exact cell/contentView with textField.superview, convert it to MyTableViewCell, then use tableView.indexPath(for: cell) to get index.

No need for tags to do it.

Example:

var view: UIView = textField
while !view.isKind(of: UITableViewCell.self), let superView = view.superview {
    view = superView
}
if let view = view as? MyTableViewCell {
   //Do sth
}
Tj3n
  • 9,837
  • 2
  • 24
  • 35
  • This won’t compile as it stands, because `view` is implicitly typed as UITextField. You must explicitly type it as UIView. – matt Sep 17 '20 at 05:21
1

in cellForRow

var section = indexPath.section + 1
var row = indexPath.row + 1
index = Int("\(section)0\(row)")!

setting the textFields' tags to index

in textFieldDidBeginEditing

let indexString = "\(textField.tag)"
let parts = indexString.components(separatedBy: "0")
let row = Int(parts[1])! - 1
let section = Int(parts[0])! - 1
Noah Iarrobino
  • 1,435
  • 1
  • 10
  • 31
1

Easiest way to get indexPath of cell that contain textfield

func getIndexPathFromView(_ sender : UIView) -> IndexPath? {
    let point = sender.convert(CGPoint.zero, to: self.tblView)
    let indexPath = self.tblView.indexPathForRow(at: point)
    return indexPath
}
Dhawal
  • 1,055
  • 6
  • 10
0

I am not too familiar with the UITextField delegate. In my own way, to find the index path of the cell with the text field that is currently being edited. I created an IBAction outlet, editingTextField, that its event is "Editing did begin". So, whenever a user clicks on the text field, this function is invoked. Also, I created an array var cellArray = [UITableViewCell]() that is appended each cell in cellForRowAt

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CellIdentifier") as! CellIdentifier
        //whatever

        cellArray.append(cell)
        return cell
    }

You iterate through this array in your IBAction outlet and for each cell, you check if its text field is currently being edited with textField.isEditing. If the text field is in fact being edited, you can get the index path of the current cell by using tableView.indexPath(for: myCell) where myCell is the current cell instance.

See below:

    @IBAction func numberChange(_ sender: Any) {
        for cell in cellArray {
            let myCell = cell as! SelectExerciseNumTableViewCell
            if(myCell.numExercisesField.isEditing) {
                //indexPath is declared outside of this scope
                indexPath = tableView.indexPath(for: myCell)
            }
        }
    }

You can also use this to update text in the current cell, which is what I used it for.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Kyle F.
  • 43
  • 7