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