19

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.

Bourne
  • 10,094
  • 5
  • 24
  • 51

2 Answers2

5

I've had this same problem. Try using:

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView              
harpreetSingh
  • 1,354
  • 1
  • 10
  • 12
Brett George
  • 141
  • 2
  • 7
  • The question is about textfield and you suggest textview delegate method. I don't get it, what's the point? – pronebird Aug 04 '15 at 19:10
  • 1
    The answer might be irrelevant to this problem but it solved the issue in my case. Thanks! – Ke MA Jan 16 '18 at 16:25
  • textField has a simliar delegate method, I would imagine that it likewise will solve the problem: textFieldShouldBeginEditing – Andy Weinstein Oct 25 '20 at 22:39
4

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.

Lyndsey Scott
  • 37,080
  • 10
  • 92
  • 128