Swift: retrieving text from a UITextField in a custom UITableViewCell and putting it in an array
There is a problem with your approach if the number of rows in your table exceeds the number that can fit on screen. In that case, the cells that scroll off-screen will be re-used, and the contents of the nameInput
textField will be lost. If you can be sure that this will never happen, use the following code (in the method that handles button taps) to compose your array:
var arrayOfNames : [String] = [String]()
for var i = 0; i<self.arrayOfPeople.count; i++ {
let indexPath = NSIndexPath(forRow:i, inSection:0)
let cell : EditingCell? = self.tableView.cellForRowAtIndexPath(indexPath) as EditingCell?
if let item = cell?.nameInput.text {
arrayOfNames.append(item)
}
}
println("\(arrayOfNames)")
Alternatively....
However, if it is possible that cells will scroll off-screen, I suggest a different solution. Set the delegate
for the nameInput
text fields, and then use the delegate methods to grab the names as they are entered.
First, add variables to your view controller, to hold the array and the row number of the text field currently being edited.
var arrayOfNames : [String] = [String]()
var rowBeingEdited : Int? = nil
Then, in your cellForRowAtIndexPath
method, add:
cell.nameInput.text = "" // just in case cells are re-used, this clears the old value
cell.nameInput.tag = indexPath.row
cell.nameInput.delegate = self
Then add two new functions, to catch when the text fields begin/end editing:
func textFieldDidEndEditing(textField: UITextField) {
let row = textField.tag
if row >= arrayOfNames.count {
for var addRow = arrayOfNames.count; addRow <= row; addRow++ {
arrayOfNames.append("") // this adds blank rows in case the user skips rows
}
}
arrayOfNames[row] = textField.text
rowBeingEdited = nil
}
func textFieldDidBeginEditing(textField: UITextField) {
rowBeingEdited = textField.tag
}
When the user taps the button, they might still be editing one of the names. To cater for this, add the following to the method that handles the button taps:
if let row = rowBeingEdited {
let indexPath = NSIndexPath(forRow:row, inSection:0)
let cell : EditingTableViewCell? = self.tableView.cellForRowAtIndexPath(indexPath) as EditingTableViewCell?
cell?.nameTextField.resignFirstResponder()
}
This forces the textField to complete editing, and hence trigger the didEndEditing
method, thereby saving the text to the array.
How can I take the text from UITextFields in UITableViewCells in a UITableView and put them into an array (Swift 3)?
I am going to make a lot of assumptions here since you did not provide some sample code.
Lets say that you are using a UIViewController
that has a UITableView
inside it
class CalculatorViewController
@IBOutlet var tableView: UITableView!
var values: [Double] = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
}
Now you have a basic viewController but the compiler will say that CalculatorViewController does not conform to UITableViewDataSource
and UITableViewDelegate
. Let's fix that
extension CalculatorViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
// return your number of sections, let say it's one
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Let's say you only have 3 cells at the moment
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "YourCustomInputFieldCell") as! YourCustomInputFieldCell
return cell
}
}
Let's fix the UITableViewDelegate
error
extension CalculatorViewController: UITableViewDelegate {
// This one gets called each time a cell will be displayed (as it says)
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if let cell = cell as? YourCustomInputTextField {
// I assume that you expose your cell's input field
// By setting a tag on the input field you can
// distinguish it from other inputs
cell.input.tag = indexPath.row
cell.input.delegate = self
}
}
}
Again the compiler will complain that CalculatorViewController
does not conform to UITextFieldDelegate
. Let's fix that too.
extension CalculatorViewController: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Here you can check the tag of the textField
// and update the values array accordingly
// You should probably convert the string that you get to
// the number format that you want
return true
}
}
Hope it helps.
How to get user input from UItextfield and add it to an array?
As far as I could suggest (without any code insight given) you could do the following:
- Use a callback in your cell, which gets called every time the textfield ends editing:
.
class MyTableViewCell: UITableViewCell {
var textHasChanged: ((String) -> Void)?
...
}
extension MyTableViewCell: UITextFieldDelegate {
// this gets called every time the user ends editing the text field
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
let newValue = textField.text //here you have your value
// now save it to your data source
self.textHasChanged(newValue)
}
}
In a initializer or in
awakeFromNib()
function (depends on your usage), set the.delegate
property of the textfield toself
Now, to have each cell display the value from the datasource and to apply the changed text to your tableView datasource, add the following lines to your UITableViewController:
.
class MyTableViewController: UITableViewController {
var textArray: [String] = ["abc", "def"]
...
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath)
cell.textField.text = textArray[indexPath.row]
cell.textHasChanged = { (newValue) in
self.textArray[indexPath.row] = newValue
}
return cell
}
Just comment if you have further questions
Read Data From Text Field in TableView Dynamic Cell in Swift
I would change couple of things,
1. Get rid of numberOfTextFields
2. Use var cards = [Cards]()
to return the number of cells in tableView
3. Initialize cards
with a single Cards
instance and set its property to nil. So I would have Cards implementation as
struct Cards {
var frontLabel: String?
var backLabel: String?
}
4. Initialize cards
array as
var cards = [Cards()]
5. Return number of rows from arrays count
func numberOfSections(in tableView: UITableView) -> Int {
return cards.count
}
6. I would migrate text field delegate responsibilities to Cell instead of moving it to ViewController and I would have a delegate in AddFCCell
to update the ViewController about text changes
@objc protocol AddFCCellDelegate {
func updateCard(with frontText: String?, backText: String?, for cell: AddFCCell)
}
class AddFCCell: UITableViewCell {
weak var delegate:AddFCCellDelegate?
//.... other codes of yours
}
extension AddFCCell: UITextFieldDelegate {
func textFieldDidEndEditing(_ textField: UITextField) {
self.delegate?.updateCard(with: self.textField1.text, backText: self.textField2.text, for: self)
}
}
7. Finally, implement/confirm to AddFCCellDelegate
in viewController and reload TableView bu updating text
extension ViewController: AddFCCellDelegate {
func updateCard(with frontText: String?, backText: String?, for cell: AddFCCell) {
guard let indexPath = self.tableView.indexPath(for: cell) else {
return
}
self.cards[indexPath.row].frontLabel = frontText
self.cards[indexPath.row].backLabel = backText
self.tableView.reloadRows(at: [indexPath], with: .automatic)
}
}
8. Update CellForRowAtIndexPath
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "AddFCCell") as! AddFCCell
cell.selectionStyle = .none
cell.delegate = self
cell.textField1.text = cards[indexPath.row].frontLabel
cell.textField2.text = cards[indexPath.row].backLabel
cell.backgroundColor = .purple
return cell
}
You can obviously implement a efficient protocol and return/update only specific variable in Cards struct based on which textField was modified n all, but the code posted here is only to give you an idea and to get started with
EDIT 1:
Make sure you have set your TextFields delegate right
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(textField1)
textField1.delegate = self
contentView.addSubview(textField2)
textField2.delegate = self
configureTextBox1(textField: textField1)
configureTextBox2(textField: textField2)
}
Retrieve textfield.text which is inside custom cell
Method 1:
Make an array of key pairs as-
var arrayOfKeyPairs = [[String:Any]]()
arrayOfKeyPairs.append(["header":"xx",
"value" : "",
“id”: "dsd",
"order" : 0])
We are just replacing the default values with user input values as-
func textFieldDidEndEditing(_ textField: UITextField) {
let center: CGPoint = textField.center
let rootViewPoint: CGPoint = textField.superview!.convert(center, to: tableView)
let indexPath: IndexPath = tableView.indexPathForRow(at: rootViewPoint)! as IndexPath
arrayOfKeyPairs[indexPath.row ]["value"] = textField.text//here you are appending(replacing) data to array
}
On click of submit button, cross check what you received as-
func tapsOnNext(){
self.view.endEditing(true)//for adding last text field value with dismiss keyboard
print(arrayOfKeyPairs)
}
Method 2:
We can get cell data by accessing the cell with particular indexpath
as
func tapsOnNext(){
let indexpath = IndexPath(row: 0, section: 0)
let cell = tableView.cellForRow(at: indexPath) as! CustomTableViewCell
print(cell.myTextField.text)
}
Related Topics
Setting "Applelanguages" Doesn't Change App Language
My Swift 4 Uiscrollview with Autolayout Constraints Is Not Scrolling
How to Send Multiple Parameterts to PHP Server in Http Post
How to Get Core Data Object from Specific Object Id
How to Create Border in Uibutton
Connect Outlet of a Cell Prototype in a Storyboard
How to Display the Standard Checkmark on a Uicollectionviewcell
How to Programmatically Use iOS Voice Synthesizers? (Text to Speech)
How to Disable Afnetworking Cache
@Property/@Synthesize Equivalent in Swift
How to Keep Uiswitch State When Changing Viewcontrollers
iPhone Different Screen Sizes in Flash? (Getting Black Bars)
How to Present View Controller from Right to Left in iOS Using Swift
What Is a Provisioning Profile Used for When Developing iPhone Applications
Save and Retrieve Value via Keychain
Ios: Add Imageview in a Scrollview to Have Zoom
In Swiftui, How to Use Uihostingcontroller Inside an Uiview or as an Uiview