oyalhi
oyalhi

Reputation: 3994

How to update a UITableView so that UITextField in a cell won't lose focus

The setup: The table has 1 custom cell. This cell has 1 text box. In each text box a number is entered. The tableView has 5 rows (of this cell). If I change one number in any of the cells, then all the cells need to be updated, I simply call tableView.reloadData(). The change in the text box is handled with the editingDidEnd event.

The problem: I click any of the textFields and change the number. Then, I click another textField to change its value. first editingDidEnd is called, all the values are re-calculated, and tableView.reloadData is called. Now, the click to the second textField is missed because the table is reloaded.

I am not able to update the cells directly because they are custom cells and the value is changed within that class. I cannot update ALL the cells from custom cell class.

A difficult question to explain in writing especially for a non native English speaker. If you understand the question, any pointers will be appreciated :).

Using Xcode 7.1 and Swift. Thank you.

Upvotes: 6

Views: 5482

Answers (3)

yoAlex5
yoAlex5

Reputation: 34451

iOS update UITableView without reloading

In case when you should:

  • update TableView cell with UITextField and don't lose focus

A good variant when text is changed you can pass view as a parameter in closure which is responsible for listening chnages

or

func updateCell() {
    let cells = self.tableView.visibleCells
    for cell in cells {
        guard let cell = cell as? MyTableViewCell else {
            continue
        }
            
        guard let indexPath = self.tableView.indexPath(for: cell) else {
            return
        }
        
        let section = self.sections[indexPath.section]
        //logic
    }
}
  • update header/footer without reloading section
func updateFooter(sectionIndex: Int) {
    guard let footerView = self.tableView.footerView(forSection: sectionIndex) as? MyFooterView else { return }

    UIView.setAnimationsEnabled(false)
    tableView.beginUpdates()

    //logic

    footerView.sizeToFit()

    tableView.endUpdates()
    UIView.setAnimationsEnabled(true)
}

Upvotes: 0

EricLeaf
EricLeaf

Reputation: 902

This can be quite simple, ideally you are in a position to store the values for the field you want to focus and the index path of the cell in question (such as when you regenerate the editing field after your reload?)

This code should help:

- (void)tableView:(UITableView *)tableView
  willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(indexPath == self.editingIndexPath)
    {
        [self.editingTextField becomeFirstResponder];
    }
}

Upvotes: 2

Craig Siemens
Craig Siemens

Reputation: 13296

When you call reloadData, all the cells are removed from the tableview and re-added. Since it is removed, it is no longer in the responder chain meaning its text field can't be the firstResponder (selected).


There are two options that could work.

Keep track of the row that is selected, call reloadData then call becomeFirstResponder on the text field for the correct row.

Not call reload data and just update the values in the text fields. This option more depends on the striation of your app.

Upvotes: 4

Related Questions