如何获取位于 collectionviewcell 中的 TextField 文本?

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

我对 Swift 有点陌生,我想做的是获取用户在位于集合视图单元格内的 TextField 中键入的文本。我有一个名为 "PestañaCero" 的 CollectionViewCell,我在其中创建了 TextField,这个:

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

}

我试图在触摸在我的 cellForItemAt 中创建的按钮时打印文本,该代码位于我的 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)



    }  

非常感谢任何帮助,谢谢大家

您可以在创建单元格时将单元格内的textField的委托设置为控制器,cell.NumerodeContactoTextField.delegate = self然后在控制器中使用委托。但是,这种方法的问题是您必须对所有文本字段执行此操作,因此更好的解决方案是在单元格中创建您自己的委托,如下所示:

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

然后将此添加到您的单元格中:

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

现在,在控制器中创建单元格时,您需要执行以下操作:

cell.textFieldDelegate = self

在控制器中符合并实现委托:

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

这只是您将如何处理这种情况的示例。您应该能够根据您的要求进行修改。

关于如何使用上述方法执行此操作的小示例

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([=15=].text ?? "Empty Field")
        }
    }

}

您可能还必须处理单元格的出队,但现在测试此代码并进行相应修改。

@objc func confirmarbutton(sender:UIButton)
{

    let indexPath = self.collView.indexPathForItem(at: sender.convert(CGPoint.zero, to: self.collView))
    let cell = self.collView.cellForItem(at: indexPath!) as! PestañaCero

    print(cell.NombreUsuarioTextField.text) // use textfield value like this

    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(sender:)) , for: .touchUpInside)
    myCell.addSubview(nombre)

}

您可以使用索引路径访问任何行,您只需要在 cellForItem 方法中传递特定的索引路径即可获取该行,因此我只需传递我的发件人并找到该行以获取该文本字段值您只需将我的代码替换为您的代码即可它会起作用:)

这是一个我个人遵循的简单解决方案:

首先我们应该能够弄清楚用户点击了 index/row 的按钮,以便知道我们将 "indexPath" 设置为按钮层,如下面的 * cellForItemAt* 方法:

nombre.layer.setValue(indexPath, forKey: "indexPath")

然后我们需要更改 confirmarbutton 方法的签名,如下所示(如@Mahesh Dangar 在回答中所写):

@objc func confirmarbutton(sender:UIButton)

然后我们需要 confirmarbutton 方法中的 indexPath 以便我们可以先获取单元格,然后获取文本字段以访问该单元格的值文本字段:

@objc func confirmarbutton(sender:UIButton){

    let indexPath = sender.layer.value(forKey: "indexPath") as! IndexPath
    let cell = collectionView.cellForItem(at: indexPath) as! PestañaCero

    let number = cell.NombreUsuarioTextField.text! // make sure you have value in textfield else you will get runTime error

   //below is safer alternative to above line...write one of them

    if let isNumberEntered = cell.NombreUsuarioTextField.text{
          //condition will be true if text field contains value
    }else{
         //This block will be executed if text field does not contain value/it is empty. you can show alert something like please enter the number etc.
    }
}