Search code examples
swiftdelegatestableviewtextfield

Get row and section with textfield delegate method Swift


I'm kind new at swift... I need to pass the indexpath to the texfield delegate method. With "tag" I can pass only row or section.

My code:

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

        
        switch indexPath.section {

        case 1:
            cell.titulo.text = checklist.datosDomestica?.titulos[indexPath.row] ?? ""
            cell.valor.tag = indexPath.row
            cell.valor.delegate = self
            return cell
        case 2:
           
            cell.titulo.text = checklist.datosFrigoDomestica?.titulos[indexPath.row] ?? ""
            cell.valor.tag = indexPath.row
            cell.valor.delegate = self
            return cell
        case 3:
           
            cell.titulo.text = checklist.otrosDatosDomestica?.titulos[indexPath.row] ?? ""
            cell.valor.tag = indexPath.row
            cell.valor.delegate = self
            return cell
        default:
            return cell
        }


 func textFieldDidEndEditing(_ textField: UITextField) {
    
    let row = textField.tag
    
    if let texto = textField.text{
        ¿?need the section!
    }

}

I have seen answers like computing the result in the tag value but I don't see it as a good practice

Thank you!


Solution

  • Using tags is quite fragile, and generally not recommended. Instead I recommend using the coordinates of the text field's frame to figure out which cell contains it. Use the following extension to UITableView:

    //  Created by Duncan Champney on 12/23/16.
    //  Copyright © 2016-2017 Duncan Champney.
    //  May be used freely in for any purpose as long as this copyright
    //  notice is included.
    //
    import UIKit
    
    public extension UITableView {
        
        /**
         This method returns the indexPath of the cell that contains the specified view
         - Parameter view: The view to find.
         - Returns: The indexPath of the cell containing the view, or nil if it can't be found
         */
        
        func indexPathForView(_ view: UIView) -> IndexPath? {
            let center = view.center
            
            //The center of the view is a better point to use, but we can only use it if the view has a superview
            guard let superview = view.superview else {
                //The view we were passed does not have a valid superview.
                //Use the view's bounds.origin and convert from the view's coordinate system
                let origin = self.convert(view.bounds.origin, from: view)
                let indexPath = self.indexPathForRow(at: origin)
                return indexPath
            }
            let viewCenter = self.convert(center, from: superview)
            let indexPath = self.indexPathForRow(at: viewCenter)
            return indexPath
        }
    }
    

    So your delegate method would look like this:

    func textFieldDidEndEditing(_ textField: UITextField) {
        if let indexPath = tableView.indexPathForView(textField) {
            let row = indexPath.row
            let section = indexPath.section
        } else {
            // Can't find the IndexPath. Handle error
        }
    }
    
    

    You can find a working application using that code at this github link: TableViewExtension