如何从 TextFields 获取值并将该值附加到 Swift 中 TableViewCell 的 DataModel 中?

问题描述 投票:0回答:2

我有一个包含货币数组的 TableView。该数组可以有多个元素,TableView 单元格包含一个 TextField。

用户可能会或可能不会添加所有货币的价格。我已经实现了 textFieldDidEndEditing 委托方法来获取 textField 的值。这是我的 CellForRowAt:


struct PriceModel {
    var country : CountryListData?
    var price : String?
    var cancel : Bool?
    
    init(country: CountryListData? = nil, price: String? = nil, cancel: Bool? = nil) {
        self.country = country
        self.price = price
        self.cancel = cancel
    }
}


// MARK: - Variables
    var priceArray = [PriceModel]()
    var countryArray = [CountryListData]()
    var onSaveClick : (([PriceModel])->Void)?
    var textFieldValues: [IndexPath: String] = [:]



func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "PriceTableViewCell", for: indexPath) as! PriceTableViewCell
        let obj = self.countryArray[indexPath.row]
        cell.editPriceCodeLabel.text = obj.iso_code ?? ""
        cell.editPriceTextField.tag = indexPath.row
        cell.editPriceTextField.delegate = self
        if let value = self.textFieldValues[indexPath] {
            cell.editPriceTextField.text = value
            print("value --> \(value) at index --> \(indexPath.row)")
            let price = PriceModel(country: obj, price: value, cancel: true)
            print("price --> \(price)")
            self.priceArray.append(price)
            print("priceArray --> \(self.priceArray)")
        }
        
        cell.selectionStyle = .none
        return cell
    }

// MARK: - TextField Delegate
extension PriceScreen: UITextFieldDelegate {
    func textFieldDidEndEditing(_ textField: UITextField) {
        let indexPath = IndexPath(row: textField.tag, section: 0)
        self.textFieldValues[indexPath] = textField.text ?? ""
        print("self.textFieldValues --> \(self.textFieldValues)")
        self.retailPriceTableView.reloadRows(at: [indexPath], with: .automatic)
    }
}

我的代码有问题。我注意到,如果我不关闭键盘,文本字段中的值不会添加到

self.textFieldValues[indexPath]
变量中。我不确定我是否使用正确的方法来获取值。有人可以帮助我或提供指导吗?任何类型的帮助将不胜感激。

谢谢您!

ios swift uitableview uitextfield
2个回答
0
投票

无论是分配文本字段的

.delegate
还是使用更“Swifty”的闭包方法,您都希望在编辑字段时更新数据,而不是在
textFieldDidEndEditing
上更新数据。

因此,在您的

PriceTableViewCell
中,我们将宣布关闭:

var priceClosure: ((PriceTableViewCell, String) -> ())?

然后,我们将向文本字段添加目标操作:

textField.addTarget(self, action: #selector(didEdit(_:)), for: .editingChanged)

并且,这个选择器/函数:

@objc func didEdit(_ sender: UITextField) {
    // inform the controller that the text field text was edited
    priceClosure?(self, textField.text ?? "")
}

在您的控制器中,在

cellForRowAt
中,我们将分配闭包:

// add the closure
c.priceClosure = { [weak self] aCell, aStr in
    guard let self = self,
          let idx = self.tableView.indexPath(for: aCell)
    else { return }
    self.myData[idx.row].price = aStr
    self.updateTotal()
}

在编辑字段时将调用该闭包...无需等待用户点击不同的字段或手动关闭键盘。

这是一个快速完整的示例...


简单标签和文本字段单元格类 - 带有闭包:

class PriceTableViewCell: UITableViewCell { var priceClosure: ((PriceTableViewCell, String) -> ())? let label = UILabel() let textField = UITextField() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) commonInit() } required init?(coder: NSCoder) { super.init(coder: coder) commonInit() } private func commonInit() { [label, textField].forEach { v in v.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(v) } let g = contentView.layoutMarginsGuide NSLayoutConstraint.activate([ label.leadingAnchor.constraint(equalTo: g.leadingAnchor), label.centerYAnchor.constraint(equalTo: g.centerYAnchor), textField.topAnchor.constraint(equalTo: g.topAnchor), textField.trailingAnchor.constraint(equalTo: g.trailingAnchor), textField.bottomAnchor.constraint(equalTo: g.bottomAnchor), textField.widthAnchor.constraint(equalToConstant: 120.0), ]) textField.borderStyle = .roundedRect textField.keyboardType = .decimalPad textField.addTarget(self, action: #selector(didEdit(_:)), for: .editingChanged) } @objc func didEdit(_ sender: UITextField) { // inform the controller that the text field text was edited priceClosure?(self, textField.text ?? "") } }


简化的价格模型

struct PriceModel { var name: String = "" var price: String = "" }


示例控制器类 - 顶部有“运行总计”标签:

class PriceScreenVC: UIViewController { var myData: [PriceModel] = [ PriceModel(name: "A", price: ""), PriceModel(name: "B", price: ""), PriceModel(name: "C", price: ""), PriceModel(name: "D", price: ""), ] let runningTotalLabel = UILabel() let tableView = UITableView() override func viewDidLoad() { super.viewDidLoad() [runningTotalLabel, tableView].forEach { v in v.translatesAutoresizingMaskIntoConstraints = false view.addSubview(v) } let g = view.safeAreaLayoutGuide NSLayoutConstraint.activate([ runningTotalLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0), runningTotalLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0), runningTotalLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0), tableView.topAnchor.constraint(equalTo: runningTotalLabel.bottomAnchor, constant: 8.0), tableView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0), tableView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0), tableView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -8.0), ]) tableView.register(PriceTableViewCell.self, forCellReuseIdentifier: "priceCell") tableView.dataSource = self tableView.delegate = self runningTotalLabel.textAlignment = .center runningTotalLabel.text = "Total: 0" } func updateTotal() { var t: Double = 0 myData.forEach { p in if let val = Double(p.price) { t += val } } runningTotalLabel.text = "Total: \(t)" } } extension PriceScreenVC: UITableViewDataSource, UITableViewDelegate { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return myData.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let c = tableView.dequeueReusableCell(withIdentifier: "priceCell", for: indexPath) as! PriceTableViewCell c.label.text = myData[indexPath.row].name c.textField.text = myData[indexPath.row].price // add the closure c.priceClosure = { [weak self] aCell, aStr in guard let self = self, let idx = self.tableView.indexPath(for: aCell) else { return } self.myData[idx.row].price = aStr self.updateTotal() } return c } }


运行时看起来像这样:


-1
投票
当你有textField.tag时,为什么还需要IndexPath,所以只需在

textFieldDidEndEditing

方法中执行以下操作:

func textFieldDidEndEditing(_ textField: UITextField) { self.textFieldValues[textField.tag] = textField.text ?? "" print("self.textFieldValues --> \(self.textFieldValues)") self.retailPriceTableView.reload }
并在

cellForRowAt

方法中替换以下代码:

if let value = self.textFieldValues[indexPath.row] { cell.editPriceTextField.text = value print("value --> \(value) at index --> \(indexPath.row)") let price = PriceModel(country: obj, price: value, cancel: true) print("price --> \(price)") self.priceArray.append(price) print("priceArray --> \(self.priceArray)") }
    
© www.soinside.com 2019 - 2024. All rights reserved.