views:

369

answers:

1

I have a tableview controller under a navigation controller. Some of my table cells contain text fields, so when I tap on them, a keyboard will show up and automatically resize (shrink) the bounds of my tableview. The bounds is then restored when the keyboard is dismissed programmatically by calling resignFirstResponder on my text field.

Some of my cells would push a new view controller into the view stack when tapped on, so I first resign my current textfield before pushing the view controller:

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (currentEditingTextField != nil) {
    [currentEditingTextField resignFirstResponder];
    currentEditingTextField = nil;
}
return indexPath;

}

The problem is when I navigate back to my table view, the bounds of the tableview is sized as if the keyboard is still there. I know this because the scroll indicator only reaches right above where the keyboard was and there is empty view space below the table view.

Anybody experienced this and know of a solution? Thanks

+1  A: 

I had the same issue. I found that I need to prevent call [UIView viewWillDisappear:] before the keyboard hides.

My solutions for this.

// useful method, thus I don't need to remember current first responder
@interface UIView (FindAndResignFirstResponder) 
- (BOOL)findAndResignFirstResonder;
@end

// ---

@implementation UIView (FindAndResignFirstResponder)
// http://stackoverflow.com/questions/1823317/how-do-i-legally-get-the-current-first-responder-on-the-screen-on-an-iphone
- (BOOL)findAndResignFirstResonder {
    if (self.isFirstResponder) {
        return [self resignFirstResponder];
    }
    for (UIView *subView in self.subviews) {
        if ([subView findAndResignFirstResonder]) {
            return YES;
        }
    }
    return NO;
}
@end

// ---

@interface MyTableViewController : UITableViewController {

    // some booleans required to track state of keyboard and view
    BOOL hidingKeyboard;
    BOOL viewWillDisappear;
    BOOL viewWillDisappearAnimated;

}

// methods for keyboard event handling
- (void)keyboardWillHide:(id)sender;
- (void)keyboardDidHide:(id)sender;

@end

// ---

@implementation MyTableViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // adding observer for keyboard events (notifications)
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
    hidingKeyboard = NO;
    viewWillDisappear = NO;
}

- (void)viewDidUnload {
    [super viewDidUnload];

    // removing observer
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)viewWillDisappear:(BOOL)animated {
    // finding and resigning first responder
    [self.view findAndResignFirstResonder];

    if (hidingKeyboard) {
        // if keyboard hide animation in process,
        //   remembering to run [super viewWillDisappear:] after keyboard hides
        viewWillDisappear = YES;
        viewWillDisappearAnimated = animated;
    } else {
        // if there is no keyboard hide animation,
        //   calling super immediately
        [super viewWillDisappear:animated]; 
    }
}

- (void)keyboardWillHide:(id)sender {
    hidingKeyboard = YES;
}

- (void)keyboardDidHide:(id)sender {
    hidingKeyboard = NO;

    if (viewWillDisappear) {
        // calling [super viewWillAppear:] after keyboard hides, if required
        viewWillDisappear = NO;
        [super viewWillAppear:viewWillDisappearAnimated];
    }
}

@end
Aleksejs