Reputation: 81
Developing an iOS application with Xcode ver 9.2, Swift.
After the RightNavigationButtonAdd is tapped, I want to insert a TableViewCell at the beginning of the TableView and focus(becomeFirstResponder) the TextField in it.
When the inserted TableViewCell is visible, it works normally. But, when the inserted TableViewCell is invisible, an error occurred because of cellForRow returns nil.
Could you tell me how?
Code of RightNavigationButtonAdd action
@objc func RightNavigationButtonAdd(_ sender: UIBarButtonItem) {
// array is ["aaa", "bbb", "ccc", "ddd", ...]
array.insert("", at: 0)
// ttableView is @IBOutlet var ttableView: UITableView!
// it is set to "No selection during editing"
ttableView.insertRows(at: [IndexPath(row:0, section:0)], with: .top)
// when inserted cell is invisible, error occured:
// "Fatal error: Unexpectedly found nil while unwrapping an Optional value"
let cell = ttableView.cellForRow(at: IndexPath(row:0, section:0)) as! TableViewCell
cell.textField.becomeFirstResponder()
cell.textField.placeholder = "input anything ..."
ttableView.scrollToRow(at: IndexPath(row:0, section:0), at: .top, animated: true)
}
Screenshot when inserted cell is visible -> it works normally
Screenshot when inserted cell is invisible -> error occured
Upvotes: 1
Views: 621
Reputation: 10105
Your code is almost fine but you are crashing because that cell is out of range, so first you have to scroll to the beginning (to make it visible), then you'll be able to get the cell at such IndexPath(row:0, section:0)
. You may check the documentation of cellForRow:
An object representing a cell of the table, or nil if the cell is not visible or indexPath is out of range.
Here the solution:
@objc func RightNavigationButtonAdd(_ sender: UIBarButtonItem) {
array.insert("", at: 0)
ttableView.insertRows(at: [IndexPath(row:0, section:0)], with: .top)
UIView.animate(withDuration: 0.3, animations: {
self.ttableView.scrollToRow(at: IndexPath(row:0, section:0), at: .top, animated: true)
}) { (success) in
let cell = self.ttableView.cellForRow(at: IndexPath(row:0, section:0)) as! TableViewCell
cell.textField.becomeFirstResponder()
cell.textField.placeholder = "input anything ..."
}
}
Upvotes: 1
Reputation: 5673
As pointed by Andrea Mugnaini's answer you need to scroll to that cell to make it's textField
to becomeFirstResponder()
. Now answering your question
[...] cellForRow returns nil. Could you tell me how?
TableView has a pool of cells that are reused when you call cellForRow(at:)
. Thus, when cell is no longer visible it goes back to pool and returned by cellForRow(at:)
later. That's because no matter how many cells you need to display in your app you actually only need the amount of cells that fits your screen. You just reuse them. The problem with this approach is that even if you want to return cell that is out of the visible part of tableView, you can't do that because there is no cell currently displaying that row (they all busy displaying rows you see right now), and for that reason cellForRow(at:)
returns nil.
Upvotes: 0