Search code examples
swifttextfieldcollectionview

How to get the TextField's text located inside a collectionviewcell?


Im kind of new with Swift, what I am trying to do is to get the text typed by an user in a TextField which is located inside a collection view cell. I have a CollectionViewCell named "PestañaCero" where I created the TextField, this one:

import Foundation
import UIKit

class PestañaCero: UICollectionViewCell
{


    let NombreUsuarioTextField: UITextField =
    {
       let nombre = UITextField()
        nombre.borderStyle = UITextBorderStyle.roundedRect
        nombre.placeholder = "Nombre de Usuario"
        nombre.textAlignment = .center
        return nombre
    }()

    let NumerodeContactoTextField: UITextField =
    {
        let nombre = UITextField()
        nombre.borderStyle = UITextBorderStyle.roundedRect
        nombre.placeholder = "Numero de Contacto"
        nombre.textAlignment = .center
        return nombre
    }()

    let DireccionOrigenTextField: UITextField =
    {
        let nombre = UITextField()
        nombre.borderStyle = UITextBorderStyle.roundedRect
        nombre.placeholder = "Direccion de Origen"
        nombre.textAlignment = .center
        return nombre
    }()

    let DireccionDestinoTextField: UITextField =
    {
        let nombre = UITextField()
        nombre.borderStyle = UITextBorderStyle.roundedRect
        nombre.placeholder = "Direccion de Destino"
        nombre.textAlignment = .center
        return nombre
    }()

    func setupViews()
    {
        addSubview(NombreUsuarioTextField)
        addSubview(NumerodeContactoTextField)
        addSubview(DireccionOrigenTextField)
        addSubview(DireccionDestinoTextField)


        //VERTICAL CONSTRAINT

        addConstraintsWithFormat("H:|-16-[v0]-16-|", views: NombreUsuarioTextField)
        addConstraintsWithFormat("H:|-16-[v0]-16-|", views: NumerodeContactoTextField)
        addConstraintsWithFormat("H:|-16-[v0]-16-|", views: DireccionOrigenTextField)
        addConstraintsWithFormat("H:|-16-[v0]-16-|", views: DireccionDestinoTextField)

        addConstraintsWithFormat("V:|-100-[v0(30)]-12-[v1(30)]-12-[v2(30)]-12-[v3(30)]", views:
        NombreUsuarioTextField,NumerodeContactoTextField, DireccionOrigenTextField ,DireccionDestinoTextField)
    }

}

Im trying to print the text when touching in a button created in my cellForItemAt, code which is located in my UICollectionViewController class

@objc func confirmarbutton()
    {
        print("123")
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
    {

        var myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "PestañaCero", for: indexPath)
        myCell.backgroundColor = UIColor.black

        let nombre = UIButton(frame: CGRect(x: myCell.frame.width/2-100, y: 400, width: 200, height: 25))
        nombre.setTitle("Pedir Domicilio", for: .normal)
        nombre.backgroundColor = UIColor.orange
        nombre.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
        nombre.addTarget(self, action: #selector(confirmarbutton) , for: .touchUpInside)
        myCell.addSubview(nombre)



    }  

Any help would be really appreciated, thanks everyone


Solution

  • You can set the delegate of the textField inside the cell to controller when the cell is created, cell.NumerodeContactoTextField.delegate = self and then use the delegate in the controller. However, the problem with this approach is that you will have to do it for all textFields, so the better solution would be create your own delegate, in cell, like this:

    protocol CollectionCellTextFieldDelegate: class {
        func textDidChanged(_ textField: UITextField)
    }
    

    And then add this to your cell:

    class PestañaCero: UICollectionViewCell {
        weak var textFieldDelegate: CollectionCellTextFieldDelegate?
    }
    

    Now in your cell creation in the controller you do:

    cell.textFieldDelegate = self
    

    Conform and implement the delegate in the controller:

    func textDidChanged(_ textField: UITextField) {
        //Here you will get the textField, and you can extract the textFields text
    }
    

    This is just an example of how you would approach this situation. you should be able to modify based on your requirement.

    A Small Sample of how You would go about doing this with above approach

    My Cell Class

    import UIKit
    
        protocol CollectionCellTextFieldDelegate: class {
                func cellTextFields(_ fields: [UITextField])
        }
    
        class Cell: UICollectionViewCell {
    
            @IBOutlet weak var fieldOne: UITextField!
            @IBOutlet weak var fieldTwo: UITextField!
            @IBOutlet weak var button: UIButton!
    
            weak var textFieldDelegate: CollectionCellTextFieldDelegate?
    
            @IBAction func buttonClicked(_ sender: UIButton) {
                guard let textFieldDelegate = textFieldDelegate else { return } //we don't have do anything if not conformed to delegate
        //otherwise pass all textFields
                textFieldDelegate.cellTextFields([fieldOne, fieldTwo])
            }
         }
    

    My Controller Class

    import UIKit
    
    class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, CollectionCellTextFieldDelegate {
    
    
        @IBOutlet weak var collectionView: UICollectionView!
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
        //register the cell xib
            collectionView.register(UINib(nibName: "Cell", bundle: nil), forCellWithReuseIdentifier: "Cell")
        }
    
        //MARK:- CollectionView
        func numberOfSections(in collectionView: UICollectionView) -> Int {
            return 1
        }
    
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 2
        }
    
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
            cell.textFieldDelegate = self
            return cell
        }
    
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
            return CGSize(width: collectionView.bounds.width - 20.0, height: 175.0)
        }
    
        //you could write this delegate anyway you want, its just for a sample
        func cellTextFields(_ fields: [UITextField]) {
    
            //loop over each fields and get the text value
            fields.forEach {
                debugPrint($0.text ?? "Empty Field")
            }
        }
    
    }
    

    You will probably have to handle dequeueing of cells as well but for now test this code and modify accordingly.