Reputation: 3028
in my app I have a UITabeView
with UITextField
s inside every cell. However I'm having troubles implementing previous/next buttons to make the text field inside the previous/next UITableViewCell
be the first responder.
I've subclassed the UITableViewCell
class to have it call a certain method of it's delegate
when the prev./next buttons are pressed and to pass the cell itself as a parameter of this method (so I can get its index path to calculate which is the index path of the cell whose text field has to be made first responder)
In the implementation of the delegate's method I:
-cellForRowAtIndexPath:
method on the table viewProblem is that the -cellForRowAtIndexPath:
method returns the cell only if it is visible. So when the cell is not visible it will return nil
and the above algorithm will not work while when the cell is on screen it will work correctly.
Here is my code for the prev. button, provided that MUInfoMateriaTableViewCell
is my subclass of UITableViewCell
and that it has a textField
property that returns its text field:
- (void)prevButtonPressedInCell:(MUInfoMateriaTableViewCell *)cell
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
NSIndexPath *previousIndexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:indexPath.section];
MUInfoMateriaTableViewCell *newCell = (MUInfoMateriaTableViewCell *)[self.tableView cellForRowAtIndexPath:previousIndexPath];
[newCell.textField becomeFirstResponder];
}
Is there any way to "get" a cell that is not visible so I can make its text field the first responder? Or can you suggest me another algorithm to work around this problem?
Upvotes: 6
Views: 2009
Reputation: 124997
Problem is that the -cellForRowAtIndexPath: method returns the cell only if it is visible.
That's because the cell doesn't exist when its row isn't visible. UITableView only keeps those cells it needs to draw the table. That's why you get lots of -tableView:cellForRowAtIndexPath:
messages when you scroll the table -- the table is asking its data source to provide the cells that it doesn't have.
If you want to use your current approach, you'll need to scroll the table so that the row about to be edited becomes visible, as demonstrated in Gabriele Petronella's answer.
Upvotes: -1
Reputation: 108101
Make the cell visibile by scrolling the table view, using scrollToRowAtIndexPath:atScrollPosition:animated:
.
For instance
- (void)prevButtonPressedInCell:(MUInfoMateriaTableViewCell *)cell
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
NSIndexPath *previousIndexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:indexPath.section];
[self.tableView scrollToRowAtIndexPath:previousIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
MUInfoMateriaTableViewCell *newCell = (MUInfoMateriaTableViewCell *)[self.tableView cellForRowAtIndexPath:previousIndexPath];
[newCell.textField becomeFirstResponder];
}
Upvotes: 4
Reputation: 7416
You can fix this with a multi-step process:
NSIndexPath
of the cell to be shown and call [self.tableView scrollToRowAtIndexPath:atScrollPosition:animated:]
to bring it into viewtableView:willDisplayCell:forRowAtIndexPath:
to call becomeFirstResponder
on the desired cell when it becomes visible and it matches the desired cell or index pathThe last step is important because calling becomeFirstResponder
doesn't do anything if the receiver isn't a subview of any window.
Upvotes: 8