【问题标题】:Read Data From Text Field in TableView Dynamic Cell in Swift从 Swift 中 TableView 动态单元格中的文本字段读取数据
【发布时间】:2021-01-27 09:56:58
【问题描述】:

我想在表格视图的动态单元格中读取文本字段中的文本。

每个单元格有两个文本字段,用户可以添加更多单元格。

我的问题: 如何从文本字段(textField1 和 textField2)中读取值并将它们添加到我的卡片结构中?

在 Cards 结构中有两个变量。 frontLabel 和 backLabel 作为字符串

我的表视图:

class AddFCViewController: UIViewController  {

   
    var numberOfTextFields = 1
    var cards = [Cards]()
    
    
    
    // Table View
    let tableView : UITableView = {
        let tableView = UITableView()
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.backgroundColor = .purple
        
        return tableView
    }()
    
   
    // Add Button
    let addButtton : UIButton = {
       let btn = UIButton()
        btn.translatesAutoresizingMaskIntoConstraints = false
        btn.backgroundColor = .link
        btn.setTitle("Ekle", for: .normal)
        return btn
    }()
    
  
    override func viewDidLoad() {
        super.viewDidLoad()
        
        configureTableView()
        configureAddButton()


        
    }
    
    
   
    
    // MARK: - Configure Add Button
    func configureAddButton() {
        view.addSubview(addButtton)
       
        addButtton.addTarget(self, action: #selector(addButtonTapped(sender:)), for: .touchUpInside)
    }
    
    // MARK: - Add Button Tapped MEthod
    @objc func addButtonTapped(sender: UIButton){
        numberOfTextFields += 1
        tableView.reloadData()
    }
    
 
    // MARK: - Configure Table View
    func configureTableView() {
        view.addSubview(tableView)
        setTableViewDelegates()
        
        tableView.rowHeight = 100
        tableView.register(AddFCCell.self, forCellReuseIdentifier: "AddFCCell")
       
        
    }
    
    // MARK: - Table View Delegates
    func setTableViewDelegates() {
        tableView.delegate = self
        tableView.dataSource = self
    }
}


// MARK: - Table View Extension & Delegate Methods

extension AddFCViewController: UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return numberOfTextFields
    }
    
    
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "AddFCCell") as! AddFCCell
        cell.selectionStyle = .none
        cell.textField1.tag = indexPath.row
        cell.textField2.tag = indexPath.row
        print(cell.textField1.tag)
        print(cell.textField2.tag)
        
//        cell.textField1.text = cards[indexPath.row].frontLabel
//        cell.textField2.text = cards[indexPath.row].backLabel
  

        cell.textField1.delegate = self
        

        cell.backgroundColor = .purple

        return cell
    }
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 10
    }
    
    func textFieldDidBeginEditing(_ textField: UITextField) {
//        textField.addTarget(self, action: #selector(valueChanged), for: .editingChanged)
    }
   
  
    
}

这是我的自定义单元类。

class AddFCCell: UITableViewCell {
   
    
    // MARK: - Text Field 1
    let textField1 : UITextField = {
        let textField = UITextField()
        textField.translatesAutoresizingMaskIntoConstraints = false
        textField.backgroundColor = .white
        textField.isUserInteractionEnabled = true
        textField.placeholder = "TYPE HERE SOMETHING"
        textField.font = UIFont.systemFont(ofSize: 20)

        return textField
    }()
    
    
    // MARK: - Text Field 2
    let textField2 : UITextField = {
        let textField = UITextField()
        textField.translatesAutoresizingMaskIntoConstraints = false
        textField.backgroundColor = .white
        textField.isUserInteractionEnabled = true
        textField.placeholder = "TYPE HERE SOMETHING"
        textField.font = UIFont.systemFont(ofSize: 20)

        return textField
    }()

    // MARK: - view Did Load
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        contentView.addSubview(textField1)
        contentView.addSubview(textField2)
        
        configureTextBox1(textField: textField1)
        configureTextBox2(textField: textField2)
    }
  
    
    // MARK: - Configure Text Box 1 Function
    func configureTextBox1(textField : UITextField) {
        
        textField.layer.cornerRadius = 20
     
    }
    
    // MARK: - Configure Text Box 2 Function
    func configureTextBox2(textField : UITextField) {
        
        textField.layer.cornerRadius = 20
     
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

PS - 我删除了一些约束代码,因为那里的代码太多了。

【问题讨论】:

  • "我如何从文本字段中读取值"什么时候?当用户点击某个特定按钮或用户停止编辑文本字段时?
  • 抱歉,缺少信息。当用户完成编辑后,我想读取数据。

标签: swift tableview swift5 custom-cell


【解决方案1】:

我会改变几件事,

1.摆脱numberOfTextFields

2.使用var cards = [Cards]()返回tableView的单元格数

3. 使用单个 Cards 实例初始化 cards 并将其属性设置为 nil。所以我将 Cards 实现为

struct Cards {
    var frontLabel: String?
    var backLabel: String?
}

4.cards数组初始化为

var cards = [Cards()]

5.从数组计数返回行数

    func numberOfSections(in tableView: UITableView) -> Int {
        return cards.count
    }

6.我会将文本字段委托职责迁移到 Cell 而不是将其移动到 ViewController,并且我将在 AddFCCell 中有一个委托来更新 ViewController 的文本更改

@objc protocol AddFCCellDelegate {
    func updateCard(with frontText: String?, backText: String?, for cell: AddFCCell)
}

class AddFCCell: UITableViewCell {
    weak var delegate:AddFCCellDelegate?
    //.... other codes of yours
}

extension AddFCCell: UITextFieldDelegate {
    func textFieldDidEndEditing(_ textField: UITextField) {
        self.delegate?.updateCard(with: self.textField1.text, backText: self.textField2.text, for: self)
    }
}

7.最后,在viewController中实现/确认AddFCCellDelegate并重新加载TableView bu更新文本

extension ViewController: AddFCCellDelegate {
    func updateCard(with frontText: String?, backText: String?, for cell: AddFCCell) {
        guard let indexPath = self.tableView.indexPath(for: cell) else {
            return
        }
        self.cards[indexPath.row].frontLabel = frontText
        self.cards[indexPath.row].backLabel = backText
        self.tableView.reloadRows(at: [indexPath], with: .automatic)
    }
}

8.更新CellForRowAtIndexPath

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "AddFCCell") as! AddFCCell
        cell.selectionStyle = .none
        cell.delegate = self
        cell.textField1.text = cards[indexPath.row].frontLabel
        cell.textField2.text = cards[indexPath.row].backLabel


        cell.backgroundColor = .purple

        return cell
    }

您显然可以实现一个高效的协议并仅返回/更新 Cards 结构中的特定变量,具体取决于哪个 textField 被全部修改,但此处发布的代码只是为了给您一个想法并开始使用

编辑 1:

确保您已正确设置 TextFields 委托

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        contentView.addSubview(textField1)
        textField1.delegate = self
        contentView.addSubview(textField2)
        textField2.delegate = self

        configureTextBox1(textField: textField1)
        configureTextBox2(textField: textField2)
    }

【讨论】:

  • 谢谢桑迪普。您的回答肯定推动了我前进,但是我仍然无法访问这些 textField 值。我用您的答案更新了我的代码并对其进行了调试,并且 Cards 对象 textFields 返回 nil 值。 drive.google.com/file/d/1nBytLl0HkpzVrsBCs_WbdwE8oiCUlO1f/…
  • @evrim-demir:显示您的单元格代码,同时放置一个断点并检查您的文本字段代表是否在单元格上触发(甚至在此之前确保您已将单元格设置为文本字段代表)
  • @evrim-demir:你还没有做我在回答中提到的任何事情,并且期望代码能够工作? 1.您将 textfields 委托设置为 ViewController,我已删除检查 cellForRowAt 方法,我已明确删除 cell.textField1.delegate = self 和 textField2 2.您尚未将 ViewController 设置为单元格 cell.delegate = self 的委托检查@ 987654343@ 再次 3. 您还没有将单元格设置为文本字段委托检查init AddFCCell 的方法,显然我已经添加了textField1.delegate = self 如果这些东西都没有设置,它将如何工作?
  • @evrim-demir:如果数据源不一致,例如您向数组中添加了一张卡片但尚未重新加载表格视图,或者您已删除一张卡片但尚未更新表格视图,则会发生这种情况在这种情况下,tableView 将具有导致这些崩溃的单元格的过时索引路径,您必须小心解决这些问题,显而易见且简单的解决方案是调用 self.tableView.reloadData() 而不是 self.tableView.reloadRows(at: [indexPath], with: .automatic) 但这不会有效,如果你有行数相当少,没有时间分析问题使用它
【解决方案2】:

您可以将占位符文本添加到两个文本字段,确保两个占位符文本不同,这里我尝试将 uniq 标识符分配给带有标签的文本字段。

&

通过比较 textFieldDidBeginEditing 中的占位符文本来检索文本字段值。

cell.textField1.tag = indexPath.row

cell.textField2.tag = indexPath.row

cell.textField1.placeholder = "1"

cell.textField2.placeholder = "2"

func textFieldDidBeginEditing(_ textField: UITextField) {

  if(textField.tag && placeholder){
  }

}

这不是一个合适的解决方案,但通过这种方式,您可以区分具有相同标签的两个文本。

【讨论】:

    猜你喜欢
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2020-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多