Shift
Shift

Reputation: 43

Gather textfield text from a tableview cell (Swift)

I have a tableview with one textfield in each cell. I added a target like this:

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

    cell.cellTextField.addTarget(self, action: #selector(ViewController.TextfieldEditAction), for: .editingDidEnd)

    return cell
}

But found out that I'm not able to use the indexpath.row / sender.tag to get the specific textfield text

@objc func TextfieldEditAction(sender: UIButton) {
}

So my question is how can I get the text after the user has edited one of the textfields.

Also how can i get the indexpath.row or sender.tag which will be used to collect the text they added to that specific textfield.

Upvotes: 0

Views: 1759

Answers (2)

Harsh Vardhan Kushwaha
Harsh Vardhan Kushwaha

Reputation: 126

Following is the extension of UIView that can be used to get the cell or indexPath of the cell enclosing textField

extension UIView {

    var tableViewCell : UITableViewCell? {

        var subviewClass = self

        while !(subviewClass is UITableViewCell){

            guard let view = subviewClass.superview else { return nil }

            subviewClass = view
        }
        return subviewClass as? UITableViewCell
    }

    func tableViewIndexPath(_ tableView: UITableView) -> IndexPath? {

        if let cell = self.tableViewCell {

            return tableView.indexPath(for: cell)

        }
        return nil
    }
}

Example :-

    @objc func TextfieldEditAction(sender: UITextField) {

        //replace tableView with the name of your tableView
        guard let indexPath = sender.tableViewIndexPath(tableView) else {return}

    }

Upvotes: -2

Ashley Mills
Ashley Mills

Reputation: 53131

The easiest way to handle this is probably to use a delegate protocol…

In your cell

protocol LevelTableViewCellDelegate: class {
    func levelTableViewCell(_ levelTableViewCell: LevelTableViewCell, didEndEditingWithText: String?)
}

class LevelTableViewCell: UITableViewCell {
    @IBOutlet private weak var cellTextField: UITextField!
    var delegate: LevelTableViewCellDelegate?

    override func awakeFromNib() {
        cellTextField.addTarget(self, action: #selector(didEndEditing(_:)), for: .editingDidEnd)
    }

    @objc func didEndEditing(_ sender: UITextField) {
        delegate?.levelTableViewCell(self, didEndEditingWithText: sender.text)
    }
}    

In your view controller

class TableViewController: UITableViewController {

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "LevelTableViewCell") as! LevelTableViewCell
        cell.delegate = self
        return cell
    }
}

extension TableViewController: LevelTableViewCellDelegate {

    func levelTableViewCell(_ levelTableViewCell: LevelTableViewCell, didEndEditingWithText: String?) {

        let indexPath = tableView.indexPath(for: levelTableViewCell)

        // Now you have the cell, indexPath AND the string
    }

Also, note that the view outlet is be private. You'll find that you write cleaner code if you follow this rule

Upvotes: 5

Related Questions