Вы никогда не хотите «получать текст из ячейки». Ячейки используются повторно, поэтому при прокрутке текстового поля, которое было в Section: 0 Row: 0
, теперь может быть в Section: 10 Row: 0
.
Вместо этого назначьте "закрытие обратного вызова" для своей ячейки в cellForRowAt
. Когда пользователь редактирует текстовое поле, попросите вашу ячейку «перезвонить» на контроллер, чтобы обновить источник данных.
Вот полный пример с небольшим изменением вашего кода:
class InputTableViewCell: UITableViewCell {
// callback closure to tell the controller the text field was edited
var callback: ((String) ->())?
let cellInputTextfield: UITextField = {
let cellInputTextfield = UITextField()
cellInputTextfield.textColor = .black
cellInputTextfield.sizeToFit()
return cellInputTextfield
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: .default, reuseIdentifier: reuseIdentifier)
cellInputTextfield.frame = CGRect(x: 20, y: 0, width: self.frame.width, height: 60)
cellInputTextfield.font = UIFont.systemFont(ofSize: 15)
self.contentView.addSubview(cellInputTextfield)
// add a target func to call when the text field is edited
cellInputTextfield.addTarget(self, action: #selector(textFieldChanged(_:)), for: .editingChanged)
}
@objc func textFieldChanged(_ textField: UITextField) -> Void {
// end the edited text back to the controller
callback?(textField.text ?? "")
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
enum JourneySection:Int, CaseIterable, CustomStringConvertible{
case Description
case ID
case Confirmation
case Destination
case DestinationDate
case DestinationTime
case Arrival
case ArrivalDate
case ArrivalTime
case PriceTotal
case Companions
var description: String {
switch self {
case .Description: return "Description"
case .ID: return "ID f.ex. Flight Number"
case .Confirmation: return "Confirmation No."
case .Destination: return "Destination"
case .DestinationDate: return "Destination Date, like DD-MM-YYYY"
case .DestinationTime: return "Destination Time, like hh-mm"
case .Arrival: return "Arrival"
case .ArrivalDate: return "Arrival Date, like DD-MM-YYYY"
case .ArrivalTime: return "Arrival Time, like hh-mm"
case .PriceTotal: return "Total Price"
case .Companions: return "No. Of Companions"
}
}
}
class JourneyViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let testButton: UIButton = {
let v = UIButton()
v.translatesAutoresizingMaskIntoConstraints = false
v.setTitle("Check Data", for: [])
v.setTitleColor(.white, for: [])
v.backgroundColor = .red
return v
}()
let tableView: UITableView = {
let v = UITableView()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
let reuseIdentifierInputCell = "journeyCell"
// declare a string data array
var dataStrings: [String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// initialize the data array with an empty string for each case
// in actual use, you may have already populated "saved" data
dataStrings = Array(repeating: "", count: JourneySection.allCases.count)
// add the button and table view
view.addSubview(testButton)
view.addSubview(tableView)
// respect safe area
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// constrain the button to Top: 20-pts and centered horizontally
testButton.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
testButton.centerXAnchor.constraint(equalTo: g.centerXAnchor),
// constrain the tableview to 8-pts below the button
// Leading / Trailing at 20-pts
// with a height of 240 (so we can see what happens when scrolling)
tableView.topAnchor.constraint(equalTo: testButton.bottomAnchor, constant: 8.0),
tableView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
tableView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
tableView.heightAnchor.constraint(equalToConstant: 240.0),
])
// register the cell class
tableView.register(InputTableViewCell.self, forCellReuseIdentifier: reuseIdentifierInputCell)
// set dataSource and delegate
tableView.dataSource = self
tableView.delegate = self
// dismiss keyboard when table scrolls
tableView.keyboardDismissMode = .onDrag
testButton.addTarget(self, action: #selector(showData(_:)), for: .touchUpInside)
}
@objc func showData(_ sender: UIButton) -> Void {
for i in 0..<JourneySection.allCases.count {
guard let section = JourneySection(rawValue: i) else {
fatalError("Something wrong with JourneySection")
}
print(section.description, ":", dataStrings[i])
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return JourneySection.allCases.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifierInputCell, for: indexPath) as! InputTableViewCell
guard let section = JourneySection(rawValue: indexPath.section) else { return UITableViewCell() }
// set placeholder
cell.cellInputTextfield.placeholder = section.description
// set the cell's text field's text
// if this entry in our data source is "", the placeholder will be shown
cell.cellInputTextfield.text = dataStrings[indexPath.section]
// we want the cell to "call us back" when the textfield is edited
cell.callback = { str in
// update our data source
self.dataStrings[indexPath.section] = str
}
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
}
Когда вы запустите его, вы должны получить:
Вы можете вводить текст в полях ... прокручивать вверх и вниз ... и когда При нажатии на кнопку «Проверить данные» вы увидите список свойств перечисления и сохраненные данные из полей.