Getting keyboard size from userInfo in Swift

There are some problems in your line:

var keyboardSize = notification.userInfo(valueForKey(UIKeyboardFrameBeginUserInfoKey))
  • notification.userInfo returns an optional dictionary [NSObject : AnyObject]?,
    so it must be unwrapped before accessing its values.
  • The Objective-C NSDictionary is mapped to a Swift native Dictionary, so you must
    use the dictionary subscript syntax (dict[key]) to access the values.
  • The value must be cast to NSValue so that you can call CGRectValue on it.

All this can be achieved with a combination of optional assignment, optional chaining and optional casts:

if let userInfo = notification.userInfo {
   if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
    let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
       // ...
   } else {
       // no UIKeyboardFrameBeginUserInfoKey entry in userInfo
   }
} else {
   // no userInfo dictionary in notification
}

Or in one step:

if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
    let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
    // ...
}

Update for Swift 3.0.1 (Xcode 8.1):

if let userInfo = notification.userInfo {
    if let keyboardSize = userInfo[UIKeyboardFrameBeginUserInfoKey] as? CGRect {
        let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
        // ...
    } else {
        // no UIKeyboardFrameBeginUserInfoKey entry in userInfo
    }
} else {
    // no userInfo dictionary in notification
}

Or in one step:

if let keyboardSize = notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? CGRect {
    let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
    // ...
}

Update for Swift 5 (Xcode 11.6):

 guard let userInfo = notification.userInfo,
              let keyboardSize = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }

I recommend using keyboardFrameEndUserInfoKey instead of keyboardFrameBeginUserInfoKey since the keyboard changes the initial render height after the first display on older iOS devices.

Leave a Comment

tech