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.

Leave a Comment