Bourne Bourne - 10 months ago 50
iOS Question

UITextField and Keyboard Notifications - strange order

So I've set up a notification for the keyboard appearance event. Now let us consider a UITextView and a UITextField.

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];


The selector is:

- (void)keyboardWillShow:(NSNotification *)notification {

keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
}


In case of a UITextView, the delegate method
- (void)textViewDidBeginEditing:(UITextView *)textView
is fired AFTER the
keyboardWillShow:
method. So keyboardSize has the keyboard's actual size and I'm able to use that inside the textview delegate method.

However in case of a UITextField, the corresponding delegate method
- (void)textFieldDidBeginEditing:(UITextField *)textField
is fired BEFORE the
keyboardWillShow:
method.

Why is this so? How do I get the keyboard's
CGSize
in the textfield's case as now it just returns zero because the textfield delegate is called first and not the keyboard selector.

Answer Source

Weird… Sounds like a mistake on Apple's end.

Maybe you could delay the keyboard popping up? Here's my unfortunately very messy "work around" suggestion -- You could send a notification when the text field is selected, but then only actually begin editing a fraction of a second later so that the text field is in fact known before keyboardWillShow: is called. For example:

-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {

    // Notification corresponding to "textFieldSelected:" method
    [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_TEXT_FIELD_SELECTED object:nil userInfo:[[NSDictionary alloc] initWithObjectsAndKeys:textField, @"textField", nil]];

    // "textFieldReallyShouldBeginEditing" is initially set as FALSE elsewhere in the code before the text field is manually selected
    if (textFieldReallyShouldBeginEditing)
        return YES;
    else
        return NO:
}

- (void)textFieldSelected:(NSNotification*)notification {

    // Done in a separate method so there's a guaranteed delay and "textFieldReallyShouldBeginEditing" isn't set to YES before "textFieldShouldBeginEditing:" returns its boolean. 
    [self performSelector:@selector(startTextFieldReallyEditing:) withObject:(UITextField*)notification[@"textField"] afterDelay:.01];
}

- (void)startTextFieldReallyEditing:(UITextField*)textField {
    textFieldReallyShouldBeginEditing = YES;

    // To trigger the keyboard
    [textField becomeFirstResponder];
}

Then depending on how you're creating the notification, you can insert the value of this now known text field even before it begins editing.