Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NilStack/71977c8c088f91640da400c99bd57707 to your computer and use it in GitHub Desktop.
Save NilStack/71977c8c088f91640da400c99bd57707 to your computer and use it in GitHub Desktop.
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
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment