After any row is deleted by deleteRows(at:with:)
from my Table View, I cannot get textfield in a reusable custom cell to get focus by becomeFirstResponder()
(which is called after insertRows(at:with:)
is called). becomeFirstResponder()
is always called within cellForRow(at:)
.
This problem always starts occuring after a row is deleted from the table view by deleteRows(at:with:)
. Before any row is deleted there is no problem, becomeFirstResponder()
can give focus to the textfield as intended.
I made some tests to understand why this problem occurs after a row is deleted... My tests showed an interesting difference:
Case 1: After any row is deleted (i.e. while becomeFirstResponder()
returns false), textFieldShouldBeginEditing(_:)
is called BEFORE cellForRow(at:)
returns. textFieldDidBeginEditing(_:)
is never called.
Case 2: On the other hand, before any row is deleted (i.e. while becomeFirstResponder()
returns true), textFieldShouldBeginEditing(_:)
is called AFTER cellForRow(at:)
returns. textFieldDidBeginEditing(_:)
is called immediately after textFieldShouldBeginEditing(_:)
, as expected.
The problem might be related to this difference, but I couldn't solve this mystery after trying & researching for many hours.
In a related Q&A, it is suggested not to reload tableView from within textFieldDidEndEditing()
. In my case, deleteRows(at:with:)
method are sometimes called from within textFieldDidEndEditing()
and sometimes called from tableView(_:commit:forRowAt:)
(i.e. by swiping to left). So this does not explain my problem. Another related Q&A might be this one.
getFocus() in CustomCell's class, called from cellForRow(at:)
in TableViewController:
func getFocus() {
if let itemTextField = itemTextField {
itemTextField.delegate = self
itemTextField.isUserInteractionEnabled = true
itemTextField.becomeFirstResponder()
}
}
cellForRow(at:)
:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item = items[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
cell.setCell(item: item)
cell.delegate = self
if insertingRow == true {
if isTempItem(item: item, indexPath: indexPath) {
cell.getFocus()
} else {
print("isTempItem returned false, no need to give focus.")
}
}
return cell
}
Don't call getFocus
in cellForRowAt
, Insteed of when you insert new row, You can scroll to new row and call getFocus
in willDisplayCell
.
Hope to help you.