85

I have been using Keyboard notifications without any problem and getting exact height of Keyboard.

- (void)keyboardDidShow:(NSNotification *) notification{
    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    NSLog(@"%f",keyboardSize.height);}

but with iOS 11 the size of keyboard is 0 when the notification is called.

What is the problem occurring in this scenario? I am using xcode 9 Beta 5

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Hassy
  • 5,068
  • 5
  • 38
  • 63

8 Answers8

191

Use this:

CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;

For Swift, you can use:

let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.size
s.zainulabideen
  • 2,047
  • 1
  • 13
  • 13
102

Replace UIKeyboardFrameBeginUserInfoKey

with

UIKeyboardFrameEndUserInfoKey

The below is from Apple Docs.

UIKeyboardFrameBeginUserInfoKey- The key for an NSValue object containing a CGRect that identifies the start frame of the keyboard in screen coordinates.

UIKeyboardFrameEndUserInfoKey - The key for an NSValue object containing a CGRect that identifies the end frame of the keyboard in screen coordinates.

Aditya Srivastava
  • 2,630
  • 2
  • 13
  • 23
  • 13
    Apple needs to update their example code then, because it doesn't work anymore on iOS 11. Also from Apple docs, where they use UIKeyboardFrameBeginUserInfoKey: https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html – wildcat12 Sep 22 '17 at 13:38
  • Solved my problem! Thanks for the advice! – Ernie Nov 15 '17 at 14:58
  • Can someone explain to me like I'm 5-years-old what the difference between these two is, and why this makes a difference when it comes to getting the UIScrollView to scroll automatically? I would really appreciate that. Thanks! – Mario Nov 29 '17 at 17:02
  • It's not working after tap to a textfield with numPad. if after numPad I tap to the general textfield, keyboard not up anymore and when it dismiss view get down – Jack Daniel Dec 13 '17 at 13:46
7

Try this:

Replace UIKeyboardFrameBeginUserInfoKey with UIKeyboardFrameEndUserInfoKey

Aditya Srivastava
  • 2,630
  • 2
  • 13
  • 23
SolinLiu
  • 209
  • 1
  • 8
  • 1
    `[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];`the method keyboardWillChangeFrame:is not only run once,maybe twice,or more.Maybe some keyboard have special toolbar on top sometimes,the method will run many times at this time.So,you should replace **UIKeyboardFrameBeginUserInfoKey** with **UIKeyboardFrameEndUserInfoKey** to get the final frame of the keyboard. – SolinLiu Aug 15 '17 at 09:47
6

This issue is happening on iOS 11.

Replace

"UIKeyboardFrameBeginUserInfoKey" with "UIKeyboardFrameEndUserInfoKey"

as shown below would fix the issue

Objective-C Code :

CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;

Swift 2.3 :

let keyboardSize = (NfnPsgVar.userInfo![UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue().size

Swift 3 :

let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.size
Community
  • 1
  • 1
Sujay U N
  • 4,974
  • 11
  • 52
  • 88
5

I had a similar issue using Xcode Version 9.0 (9A235); although I was using Swift. In my keyboardWillShow method I wrote the following:

if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {

    let heightValue = keyboardSize.height    

    ...
}

Strangely, the first time keyboardWillShow was called, heightValue was 216.0, but during subsequent calls it had become 0! Perhaps this is an Xcode bug.

I replaced the UIKeyboardFrameBeginUserInfoKey with a UIKeyboardFrameEndUserInfoKey, and it fixed the issue for me.

andym
  • 67
  • 6
  • 1
    I noticed the same thing. It also seems to only apply to the very first time the keyboard shows. Keyboards on additional view controllers reported the height as 0 the first time it showed for that view controller. – jackofallcode Nov 02 '17 at 10:16
3

Calculate keyboard height using the below code.

It is working for both devices with the safe area and non-safe area devices.

Code:

@objc func keyboardWillShow(notification: Notification) {
    guard let keyboardFrame = notification.userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else {
            return
        }    
    let keyboardHeight: CGFloat                    
    if #available(iOS 11.0, *) {
       let window = UIApplication.shared.keyWindow
       let bottomPadding = window?.safeAreaInsets.bottom ?? 0.0
       keyboardHeight = keyboardFrame.cgRectValue.height - bottomPadding
    } else {
       keyboardHeight = keyboardFrame.cgRectValue.height
    }
}
Community
  • 1
  • 1
Hitesh Surani
  • 12,733
  • 6
  • 54
  • 65
2

Your approach is trying to get the frame height before it is shown, and that is why it should be 0 which I am not sure why it is not at the first try! Here is an example of how to correctly get the keyboard height in swift 4.2:

func keyboardWillShow(notification: Notification) {

    guard let userInfo = notification.userInfo else { return }

    guard var keyboardFrame: CGRect = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return }

    keyboardFrame = view.convert(keyboardFrame, from: nil)

    let keyboardHeight = keyboardFrame.height
}

This will correctly provide the keyboard frame properties BEFORE keyboard appears.

Ramin
  • 335
  • 4
  • 14
0

Eventhough we get accurate keyboard height when we adjust BottomSpace Constraints from SafeArea it makes more empty space. So we have to subtract safeArea margin from keyboard height if we are going to adjust the bottomSpace Constraints.

    @objc func keyBoardWillShow(notification: NSNotification) {
                  
    
                  if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
                      var bottomPadding: CGFloat = 0
                      //IF device is latest including iPhone x, it will have bottom padding as safeArea Insets. So we have to subtract that from REAL Keyboard HEIGHT.
                      if let window = UIApplication.shared.windows.first{
                        bottomPadding = window.safeAreaInsets.bottom
                      }
    
                      let keyboardRectangle = keyboardFrame.cgRectValue
                      let keyboardHeight = keyboardRectangle.height - bottomPadding
                      bottomSpaceConstraint.constant = keyboardHeight
                  }
                  self.view.layoutIfNeeded()
              }
Kisoth Srinathan
  • 115
  • 2
  • 10