I have a TableView containing an Array of currencies. The array can have multiple elements, and TableView cell contains a TextField.
Users may or may not add prices for all the currencies. I have implemented textFieldDidEndEditing delegate method to get textField’s value. This is my 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)
}
}
I have a problem with my code. I noticed that if I do not dismiss the keyboard, the value from the text field does not get added to the self.textFieldValues[indexPath]
variable. I am not sure if I am using the correct method to get the values. Can someone please help me or provide guidance? Any type of assistance would be greatly appreciated.
Thank You!
2
Answers
Why do you need IndexPath when you have textField.tag, So simply do the following in
textFieldDidEndEditing
method:And replace the following code in
cellForRowAt
method:Whether assigning the text field’s
.delegate
or, using a more "Swifty" approach with a closure, you want to update your data as the field is being edited, rather than ontextFieldDidEndEditing
.So, in your
PriceTableViewCell
we’ll declare a closure:then, we’ll add a target action to the text field:
and, this selector/func:
In your controller, in
cellForRowAt
, we’ll assign the closure:That closure will be called as the field is being edited … no waiting for the user to tap into a different field or manually dismiss the keyboard.
Here is a quick complete example…
Simple label & text field cell class – with the closure:
Simplified PriceModel:
Example controller class – with a "running total" label at the top:
Looks like this when running: