如何在原型单元格中同时更改 textField.text?

How to simultaneously change textField.text in a prototype cell?

我有一个 UITableViewController 和一个带有 UITextField 的原型单元格。当我在其中一个单元格中更改 textField.text 时,我希望它在我的 tableView 现在拥有的所有其他单元格中进行更改(例如,将数字乘以 2 并设置为其他单元格的 textField.text 输出)。

这是我要实现的行为:CLICK

我应该触发某个 textField 委托方法还是应该以其他方式制作?

我现在的代码:

 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  cell.numberTextField.delegate = self
 }

//Delegate methods

func textFieldDidBeginEditing(_ textField: UITextField) {
    textField.text = ""
    textField.textColor = UIColor.systemBlue
}

func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) {
        textField.text = "0"
        textField.textColor = UIColor.black
}

在您的 textFieldDidBeginEditingtextFieldDidChangeSelection 委托中,调用 tableView.reloadData()

高级别:

  1. 您需要有一个模型来存储正在更新的数据
  2. 您需要观察使用 UITextFieldDelegate
  3. 输入的文本
  4. 输入文本时,使用新计算更新活动单元格以外的所有行

最有趣的作品在textFieldDidChangeSelectioncellForRowAt indexPath

这是我如何做这样的事情的例子:

1.设置一些自定义类型

// Your model to store data in text fields
// Maybe for you, you will store currencies
// and base currency to multiply against
// I am just storing a random number for example
struct FinanceModel
{
    var number: Int?
}

// Custom UITextField which will store info
// about cell index path as we need to identify
// it when editing
class MappedTextField: UITextField
{
    var indexPath: IndexPath!
}

2。 UITableView Cell示例,有自己的可以忽略

fileprivate class CustomCell: UITableViewCell
{
    // Use custom text field
    var textField: MappedTextField!
    
    static let tableViewCellIdentifier = "cell"
    
    override init(style: UITableViewCell.CellStyle,
                  reuseIdentifier: String?)
    {
        super.init(style: style,
                   reuseIdentifier: reuseIdentifier)
        
        configureTextField()
    }
    
    required init?(coder: NSCoder)
    {
        fatalError("init(coder:) has not been implemented")
    }
    
    // Configure text field and auto layout
    private func configureTextField()
    {
        textField = MappedTextField()
        textField.keyboardType = .numberPad
        textField.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(textField)
        
        textField.layer.borderWidth = 2.0
        textField.layer.borderColor = UIColor.blue.cgColor
        textField.layer.cornerRadius = 5.0
        
        // auto-layout
        textField.leadingAnchor.constraint(equalTo: contentView.leadingAnchor,
                                           constant: 20).isActive = true
        textField.trailingAnchor.constraint(equalTo: contentView.trailingAnchor,
                                            constant: -20).isActive = true
        textField.topAnchor.constraint(equalTo: contentView.topAnchor,
                                       constant: 20).isActive = true
        textField.bottomAnchor.constraint(equalTo: contentView.bottomAnchor,
                                          constant: -20).isActive = true
    }
}

3。在视图控制器中设置 - 如果已经设置可以跳过,这里只是为了完整性

class InputViewController: UIViewController
{
    let tableView = UITableView()
    
    // Initialize your mode
    var financeModel = FinanceModel()
    
    // This will store current editing cell which is active
    var activeTextFieldIndexPath: IndexPath?
    
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        // This is just view set up for me,
        // You can ignore this
        title = "TableView Input"
        navigationController?.navigationBar.tintColor = .white
        view.backgroundColor = .white
        
        configureTableView()
    }
    
    // Configure TableView and layout
    private func configureTableView()
    {
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.register(CustomCell.self,
                           forCellReuseIdentifier: CustomCell.tableViewCellIdentifier)
        
        tableView.dataSource = self
        tableView.delegate = self
        
        // remove additional rows
        tableView.tableFooterView = UIView()
        
        view.addSubview(tableView)
        
        // Auto layout
        tableView.leadingAnchor
            .constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
        tableView.topAnchor
            .constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        tableView.trailingAnchor
            .constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
        tableView.bottomAnchor
            .constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
    }
}

4。表视图数据源

extension InputViewController: UITableViewDataSource
{
    func tableView(_ tableView: UITableView,
                   numberOfRowsInSection section: Int) -> Int
    {
        // Random number for me
        return 10
    }
    
    func tableView(_ tableView: UITableView,
                   cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        let cell =
            tableView.dequeueReusableCell(withIdentifier:
                                            CustomCell.tableViewCellIdentifier)
            as! CustomCell
        
        // Set index path of custom text field
        cell.textField.indexPath = indexPath
        
        // Set view controller to respond to text field events
        cell.textField.delegate = self
        
        // Check if any cell is currently active
        // && if we are current cell is NOT the active one
        // We want to leave active cell untouched
        if let activeTextFieldIndexPath = activeTextFieldIndexPath,
           activeTextFieldIndexPath.row != indexPath.row
        {
            updateCell(cell, atIndexPath: indexPath)
        }
        else
        {
            // no active cell, just set the text
            updateCell(cell, atIndexPath: indexPath)
        }

        return cell
    }
    
    private func updateCell(_ cell: CustomCell,
                            atIndexPath indexPath: IndexPath)
    {
        // Retrieve number currently stored in model
        if let number = financeModel.number
        {
            // Set text of number in model * row number
            // Do any calculation you like, this is just an
            // example
            cell.textField.text =
                "\(number) x \(indexPath.row) = \(number * indexPath.row)"
        }
        else
        {
            // If no valid number, set blank
            cell.textField.text = ""
        }
    }
}

5.文本字段代表

extension InputViewController: UITextFieldDelegate
{
    // Respond to new text in the text field
    func textFieldDidChangeSelection(_ textField: UITextField)
    {
        // 1. Convert generic UITextField to MappedTextField
        // 2. && Retrieve index path from custom MappedTextField
        // 3. && Retrieve text from the text field
        // 4. && Check if text is valid number
        if let textField = textField as? MappedTextField,
           let indexPath = textField.indexPath,
           let text = textField.text,
           let number = Int(text)
        {
            // Assign local variable with index path we are editing
            activeTextFieldIndexPath = indexPath
            
            // Update number in the financial model
            financeModel.number = number
            
            // We only want to update data in visible rows so
            // get all the index paths of visible rows
            let visibleRows = self.tableView.indexPathsForVisibleRows ?? []
            
            // We want to update all rows EXCEPT active row
            // so do a filter for this
            let allRowsWithoutActive = (visibleRows).filter
            {
                    // Remove the active index path from the
                    // visible index paths
                    [=14=].section != indexPath.section ||
                        [=14=].row != indexPath.row
            }
            
            // Reload the visible rows EXCEPT active
            self.tableView.reloadRows(at: allRowsWithoutActive,
                                      with: .automatic)
        }
    }
    
    // This is just to make current text field
    // empty when editing, you can ignore
    func textFieldDidBeginEditing(_ textField: UITextField)
    {
        textField.text = ""
    }
    
    // Reset when text field is no longer being edited
    func textFieldDidEndEditing(_ textField: UITextField)
    {
        activeTextFieldIndexPath = nil
        tableView.reloadData()
    }
}

6.表视图委托

extension InputViewController: UITableViewDelegate
{
    func scrollViewDidScroll(_ scrollView: UIScrollView)
    {
        // End editing when scrolling table view
        // This is for me, you can have another way
        view.endEditing(true)
    }

    func tableView(_ tableView: UITableView,
                   heightForRowAt indexPath: IndexPath) -> CGFloat
    {
        // Return a random height
        return 80
    }
}

最终结果是这样的:

希望这足以让您踏上前进的道路。