提问人:SwiftNewbie 提问时间:10/28/2023 更新时间:10/28/2023 访问量:28
如何从 TextFields 中获取值并将该值附加到 Swift 中 TableViewCell 的 DataModel 中?
How to get value from TextFields and append that value in DataModel in TableViewCell in Swift?
问:
我有一个包含货币数组的 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]
谢谢!
答:
1赞
DonMag
10/28/2023
#1
无论是分配文本字段,还是使用带有闭包的更“Swifty”方法,您都希望在编辑字段时更新数据,而不是在 ..delegate
textFieldDidEndEditing
因此,在您的 中,我们将声明关闭:PriceTableViewCell
var priceClosure: ((PriceTableViewCell, String) -> ())?
然后,我们将向文本字段添加目标操作:
textField.addTarget(self, action: #selector(didEdit(_:)), for: .editingChanged)
并且,此选择器/func:
@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
}
}
运行时看起来像这样:
评论