Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Swift convenience wrapper for the userInfo values associated with a UIKeyboard notification
import UIKit
/// Wrapper for the NSNotification userInfo values associated with a keyboard notification.
///
/// It provides properties that retrieve userInfo dictionary values with these keys:
///
/// - UIKeyboardFrameBeginUserInfoKey
/// - UIKeyboardFrameEndUserInfoKey
/// - UIKeyboardAnimationDurationUserInfoKey
/// - UIKeyboardAnimationCurveUserInfoKey
public struct KeyboardNotification {
let notification: NSNotification
let userInfo: NSDictionary
/// Initializer
///
/// :param: notification Keyboard-related notification
public init(_ notification: NSNotification) {
self.notification = notification
if let userInfo = notification.userInfo {
self.userInfo = userInfo
}
else {
self.userInfo = NSDictionary()
}
}
/// Start frame of the keyboard in screen coordinates
public var screenFrameBegin: CGRect {
if let value = userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue {
return value.CGRectValue()
}
else {
return CGRectZero
}
}
/// End frame of the keyboard in screen coordinates
public var screenFrameEnd: CGRect {
if let value = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue {
return value.CGRectValue()
}
else {
return CGRectZero
}
}
/// Keyboard animation duration
public var animationDuration: Double {
if let number = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber {
return number.doubleValue
}
else {
return 0.25
}
}
/// Keyboard animation curve
///
/// Note that the value returned by this method may not correspond to a
/// UIViewAnimationCurve enum value. For example, in iOS 7 and iOS 8,
/// this returns the value 7.
public var animationCurve: Int {
if let number = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber {
return number.integerValue
}
return UIViewAnimationCurve.EaseInOut.rawValue
}
/// Start frame of the keyboard in coordinates of specified view
///
/// :param: view UIView to whose coordinate system the frame will be converted
/// :returns: frame rectangle in view's coordinate system
public func frameBeginForView(view: UIView) -> CGRect {
return view.convertRect(screenFrameBegin, fromView: view.window)
}
/// End frame of the keyboard in coordinates of specified view
///
/// :param: view UIView to whose coordinate system the frame will be converted
/// :returns: frame rectangle in view's coordinate system
public func frameEndForView(view: UIView) -> CGRect {
return view.convertRect(screenFrameEnd, fromView: view.window)
}
}
// Example of using KeyboardNotification to update an NSLayoutConstraint
import UIKit
final class ViewController: UIViewController {
// Outlet for a layout constraint that specifies distance from bottom of
// a subview to the bottom of the view.
//
// This constraint will be updated when the keyboard appears, disappears,
// or changes size.
@IBOutlet weak var bottomLayoutConstraint: NSLayoutConstraint!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "keyboardWillChangeFrameNotification:",
name: UIKeyboardWillChangeFrameNotification,
object: nil)
}
override func viewDidDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self)
super.viewDidDisappear(animated)
}
func keyboardWillChangeFrameNotification(notification: NSNotification) {
let n = KeyboardNotification(notification)
let keyboardFrame = n.frameEndForView(self.view)
let animationDuration = n.animationDuration
let animationCurve = n.animationCurve
let viewFrame = self.view.frame
let newBottomOffset = viewFrame.maxY - keyboardFrame.minY
self.view.layoutIfNeeded()
UIView.animateWithDuration(animationDuration,
delay: 0,
options: UIViewAnimationOptions(rawValue: UInt(animationCurve << 16)),
animations: {
self.bottomLayoutConstraint.constant = newBottomOffset
self.view.layoutIfNeeded()
},
completion: nil
)
}
}
@kristopherjohnson

This comment has been minimized.

Copy link
Owner Author

commented Sep 12, 2014

Example usage:

    // Adjust bottom vertical-space constraint when a
    // UIKeyboardWillChangeFrameNotification is received

    func keyboardWillChangeFrame(notification: NSNotification) {
        let keyboard = KeyboardNotification(notification: notification)

        let frameBegin = keyboard.frameBeginForView(view)
        let frameEnd = keyboard.frameEndForView(view)
        let originDelta = frameEnd.origin.y - frameBegin.origin.y

        bottomVerticalSpaceConstraint.constant -= originDelta
        view.setNeedsUpdateConstraints()

        let curve = keyboard.animationCurve

        UIView.animateWithDuration(keyboard.animationDuration,
            delay: 0.0,
            options: UIViewAnimationOptions(UInt(curve) << 16),
            animations: { self.view.layoutIfNeeded() },
            completion: nil)
    }
@joachimboggild

This comment has been minimized.

Copy link

commented Nov 17, 2014

Thanks a lot for this :-) These casts are really obscure...

@joachimboggild

This comment has been minimized.

Copy link

commented Nov 17, 2014

Minor correction:
line 78: Should be "end frame" instead of "start frame"...

@joachimboggild

This comment has been minimized.

Copy link

commented Nov 17, 2014

One more: Line 67: toRaw() is not working anymore. It should be:

    return UIViewAnimationCurve.EaseInOut.rawValue
@hpux735

This comment has been minimized.

Copy link

commented Aug 23, 2015

This is very awesome. Thanks!!

@mark-anders

This comment has been minimized.

Copy link

commented Jan 5, 2016

Thanks so much for this, it works great!

@christ776

This comment has been minimized.

Copy link

commented Jun 16, 2016

This is great, I was getting the wrong height (258) and I didn't know why! thanks!

@nessup

This comment has been minimized.

Copy link

commented Sep 20, 2017

Sad that Apple hasn't updated its keyboard API for Swift 3/4! Thank you so much for this gist.

@dhavalnenaagile

This comment has been minimized.

Copy link

commented Nov 29, 2017

Thanks a lot !!

@eli7ah

This comment has been minimized.

Copy link

commented May 6, 2018

All ingenious is simple. Thanx!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.