Noah Iarrobino
Noah Iarrobino

Reputation: 1543

How can I get the IndexPath of a textField in Swift

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?

Upvotes: 1

Views: 733

Answers (5)

Kyle F.
Kyle F.

Reputation: 43

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.

Upvotes: 0

Tj3n
Tj3n

Reputation: 9923

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
}

Upvotes: 2

Dhawal
Dhawal

Reputation: 1065

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
}

Upvotes: 1

matt
matt

Reputation: 535222

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
        }
    }
}

Upvotes: 4

Noah Iarrobino
Noah Iarrobino

Reputation: 1543

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

Upvotes: 1

Related Questions