Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS6 and offscreen UITextView in UITableView

I have a UITableViewController that has a UITextField in each cell. When the user hits return in a field, it automatically sets the next field to be first responder and scrolls the table to show that field, like this:

- (BOOL) textFieldShouldReturn:(UITextField *)textField 
{  
    UITextField *nextTextField=nil;
    NSInteger row;
    NSInteger section;

    if(textField == self.txtFieldA) 
    {
        nextTextField = self.txtFieldB;
        row=1; section=0;
    }
    else if(textField == self.txtFieldB) 
    {
        nextTextField = self.txtFieldC;
        row=2; section=0;
    }
    else 
    {
        [textField resignFirstResponder];
    }

    if(nextTextField) 
    {        
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
        [nextTextField becomeFirstResponder];

        [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];      
    }
}

The issue comes when you select a text field (say txtFieldA), scroll the table down so that txtFieldB is not visible, then hit enter. It works as expected on iOS5 (txtFieldB becomes the new first responder). However, on iOS6 it doesn't. It scrolls to the correct spot in the table, but the txtFieldB does not become the first responder (and I'm not sure what is -- when I hit "Back" on my nav controller, the keyboard stays visible).

When I hit "Return", txtFieldB's didBeginEditing isn't fired. If I delay [nextTextField becomeFirstResponder] by a second or so (until the scrolling animation finishes which makes nextTextField visible) it works as expected, but it seems hacky and less smooth to do that so I would rather understand what's going wrong than implement something like that.

like image 350
Ned Avatar asked Mar 02 '26 22:03

Ned


1 Answers

In my solution to this problem, I subclassed UITableViewCell to make a text field cell. In that text field cell, I overrode the -setSelected:animated:.

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    if (selected) {
        [self.textField becomeFirstResponder];
    }
}

Back in my view controller, when I want to advance to the next field, I just select the row it's in.

- (IBAction)advanceToNextTextField
{
    NSIndexPath *indexPath = [self nextIndexPathFromIndexPath:self.indexPathOfActiveField];

    [self.tableView selectRowAtIndexPath:indexPath
                                animated:YES scrollPosition:UITableViewScrollPositionNone];
    [self.tableView scrollToRowAtIndexPath:indexPath
                          atScrollPosition:UITableViewScrollPositionNone animated:YES];
}

This makes handling the the return key easy.

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    switch (textField.returnKeyType) {
        case UIReturnKeyNext: [self advanceToNextTextField]; break;
        case UIReturnKeyDone: [self resignFirstResponder]; break;
        default:              break;
    }

    return YES;
}

Hope that helps.

like image 103
Jeffery Thomas Avatar answered Mar 04 '26 10:03

Jeffery Thomas