UIKeyboardFrameBeginUserInfoKey & UIKeyboardFrameEndUserInfoKey
The start frame is where the keyboard is at the beginning of the animation: offscreen if the keyboard is being shown, or onscreen if the keyboard is being hidden. The end frame is where the keyboard will be at the end of the animation: vice versa. You can use the difference between them to write a single method that responds to both hiding and showing the keyboard.
Be sure also to use UIKeyboardAnimationCurveUserInfoKey
and UIKeyboardAnimationDurationUserInfoKey
when animating your view changes: that way, your animations and the OS's animations will be in sync.
Another hint: The documentation you linked to states, "The rectangle contained in the UIKeyboardFrameBeginUserInfoKey and UIKeyboardFrameEndUserInfoKey properties of the userInfo dictionary should be used only for the size information it contains. Do not use the origin of the rectangle (which is always {0.0, 0.0}) in rectangle-intersection operations". At least on the iPad on OS 3.2, this is not true. Both rects have the same size, while the origin, which is in screen coordinates, differs between the two.
You may find this question helpful: UIKeyboardBoundsUserInfoKey is deprecated, what to use instead?
UIKeyboardFrameBeginUserInfoKey
The UIKeyboardFrameBeginUserInfoKey will return the frame of the keyboard before the animation begins. The UIKeyboardFrameEndUserInfoKey will return the frame of the keyboard after the animation has completed. As an example, take the following snippet of code:
NSDictionary* info = [notification userInfo];
CGRect beginFrame = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGRect endFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
If you were to print the values of beginFrame
and endFrame
in the debug window, you might find something like this:
(gdb) print beginFrame
$1 = {
origin = {
x = 0,
y = 480
},
size = {
width = 320,
height = 216
}
}
(gdb) print endFrame
$2 = {
origin = {
x = 0,
y = 264
},
size = {
width = 320,
height = 216
}
}
So on an iPhone, this is showing that the keyboard will animate in from the bottom of the screen. The size of the keyboard doesn't change (as expected), but the y co-ordinates show the beginning and ending position of the keyboard.
iOS 11 - Keyboard Height is returning 0 in keyboard notification
Use this:
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
For Swift, you can use:
let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.size
Adjusting UITextView frame for using UIKeyboardFrameEndUserInfoKey not working
Hook bottom constraint of textView as IBOutlet and do this
@objc func adjustForKeyboard(_ notification: Notification) {
let userInfo = notification.userInfo!
let keyboardScreenEndFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let keyboardViewEndFrame = view.convert(keyboardScreenEndFrame, from: view.window)
if notification.name == Notification.Name.UIKeyboardWillHide {
self.textViewBottomCon.constant = 0
} else {
self.textViewBottomCon.constant = -1 * ( keyboardViewEndFrame.height + 20.0 )
}
self.view.layoutIfNeeded()
}
Also remove these 2 observers
NotificationCenter.default.addObserver(self, selector: #selector(TextViewController.adjustForKeyboard(_:)), name: NSNotification.Name.UIKeyboardDidChangeFrame, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(TextViewController.adjustForKeyboard(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
What is a constant like UIKeyboardFrameEndUserInfoKey for additional Japanese keyboard panel in iphone?
The constant is the same - UIKeyboardFrameEndUserInfoKey
. But - (void)keyboardWillShown:(NSNotification*)aNotification
event rises two times.
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 callCGRectValue
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.
swift iOS11 - identify keyboardSize height doesn't work anymore
Use UIKeyboardFrameEndUserInfoKey
instead of UIKeyboardFrameBeginUserInfoKey
UIKeyboardWillShowNotification issues with ios 11 beta 7
Use UIKeyboardFrameEndUserInfoKey because that key is for the NSValue object containing a CGRect that identifies an end frame of the keyboard in screen coordinates. Do not use UIKeyboardFrameBeginUserInfoKey.
Related Topics
Specifying One Dimension of Cells in Uicollectionview Using Auto Layout
Fixing Xcode 9 Issue: "iPhone Is Busy: Preparing Debugger Support for Iphone"
I Get Conflicting Provisioning Settings Error When I Try to Archive to Submit an iOS App
Itsappusesnonexemptencryption Export Compliance While Internal Testing
Convert Uiimage to Nsdata and Convert Back to Uiimage in Swift
How to Change the Color of the Text in a Uipickerview Under iOS 7
When Should Translatesautoresizingmaskintoconstraints Be Set to True
Xcode6: Run Two Instances of the Simulator
Using Core Data, Icloud and Cloudkit for Syncing and Backup and How It Works Together
How to Add a Container View Programmatically
Silent Push Notifications Only Delivered If Device Is Charging And/Or App Is Foreground
Fetching All Contacts in iOS Swift
Uitextview Style Is Being Reset After Setting Text Property
Didreceiveremotenotification: Fetchcompletionhandler: Open from Icon VS Push Notification
iPhone Simulator Suddenly Started Running Very Slow
Combine Onchange and Onappear Events in Swiftui View