Mover campo de text cuando el keyboard aparece rápido

Estoy usando Swift para progtwigr con iOS y estoy usando este código para mover el UITextField , pero no funciona. Llamo a la function keyboardWillShow correctamente, pero el campo de text no se mueve. Estoy usando autolayout

 override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil); NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil); } deinit { NSNotificationCenter.defaultCenter().removeObserver(self); } func keyboardWillShow(notification: NSNotification) { if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() { //let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0) var frame = self.ChatField.frame frame.origin.y = frame.origin.y - keyboardSize.height + 167 self.chatField.frame = frame println("asdasd") } } 

Se deben hacer algunas mejoras en las respuestas existentes.

En primer lugar, UIKeyboardWillChangeFrameNotification es probablemente la mejor notificación, ya que maneja los cambios que no solo se muestran / ocultan, sino también los cambios debidos a cambios de keyboard (lenguaje, usando keyboards de terceros, etc.) y rotaciones también.

En segundo lugar, los parameters de animation se pueden extraer de la notificación para garantizar que las animaciones estén correctamente juntas.

Probablemente hay opciones para limpiar este código un poco más, especialmente si te sientes cómodo con la fuerza de desenvolver el código del dictionary.

Swift 3.x / 4.x

 class MyViewController: UIViewController { // This constraint ties an element at zero points from the bottom layout guide @IBOutlet var keyboardHeightLayoutConstraint: NSLayoutConstraint? override func viewDidLoad() { super.viewDidLoad() // Note that SO highlighting makes the new selector syntax (#selector()) look // like a comment but it isn't one NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardNotification(notification:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil) } deinit { NotificationCenter.default.removeObserver(self) } @objc func keyboardNotification(notification: NSNotification) { if let userInfo = notification.userInfo { let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue let duration:TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0 let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIViewAnimationOptions.curveEaseInOut.rawValue let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw) if (endFrame?.origin.y)! >= UIScreen.main.bounds.size.height { self.keyboardHeightLayoutConstraint?.constant = 0.0 } else { self.keyboardHeightLayoutConstraint?.constant = endFrame?.size.height ?? 0.0 } UIView.animate(withDuration: duration, delay: TimeInterval(0), options: animationCurve, animations: { self.view.layoutIfNeeded() }, completion: nil) } } 

Swift 2.x

 class MyViewController: UIViewController { // This constraint ties an element at zero points from the bottom layout guide @IBOutlet var keyboardHeightLayoutConstraint: NSLayoutConstraint? override func viewDidLoad() { super.viewDidLoad() // Note that SO highlighting makes the new selector syntax (#selector()) look // like a comment but it isn't one NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.keyboardNotification(_:)), name: UIKeyboardWillChangeFrameNotification, object: nil) } deinit { NSNotificationCenter.defaultCenter().removeObserver(self) } func keyboardNotification(notification: NSNotification) { if let userInfo = notification.userInfo { let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() let duration:NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0 let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber let animationCurveRaw = animationCurveRawNSN?.unsignedLongValue ?? UIViewAnimationOptions.CurveEaseInOut.rawValue let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw) if endFrame?.origin.y >= UIScreen.mainScreen().bounds.size.height { self.keyboardHeightLayoutConstraint?.constant = 0.0 } else { self.keyboardHeightLayoutConstraint?.constant = endFrame?.size.height ?? 0.0 } UIView.animateWithDuration(duration, delay: NSTimeInterval(0), options: animationCurve, animations: { self.view.layoutIfNeeded() }, completion: nil) } } 

(Editado para tener en count el keyboard que anima fuera de pantalla en lugar de networkingucirlo, como se detalla en el impresionante comentario de @ Gabox a continuación)

Si está utilizando Auto Layout, supongo que ha configurado la restricción Espacio inferior a Superview . Si ese es el caso, simplemente tiene que actualizar el valor de la restricción. Así es como lo haces con un poco de animation.

 func keyboardWasShown(notification: NSNotification) { let info = notification.userInfo! let keyboardFrame: CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue() UIView.animateWithDuration(0.1, animations: { () -> Void in self.bottomConstraint.constant = keyboardFrame.size.height + 20 }) } 

El código 20 codificado se agrega solo para hacer aparecer un poco el campo de text sobre el keyboard. De lo contrario, el margen superior del keyboard y el margen inferior del campo de text serían conmovedores.

Cuando se descarta el keyboard, restablezca el valor de la restricción a su original.

Una solución simple es mover la vista hacia arriba con una constante de altura del keyboard.

 override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil); NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil); } func keyboardWillShow(sender: NSNotification) { self.view.frame.origin.y = -150 // Move view 150 points upward } func keyboardWillHide(sender: NSNotification) { self.view.frame.origin.y = 0 // Move view to original position } 

Swift 3

  NotificationCenter.default.addObserver(self, selector: #selector(RegisterViewController.keyboardWillShow(sender:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(RegisterViewController.keyboardWillHide(sender:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) 

Para mover su vista mientras edita el campo de text intente esto, he aplicado esto, su trabajo está bien

 func textFieldDidBeginEditing(textField: UITextField) { animateViewMoving(true, moveValue: 100) } func textFieldDidEndEditing(textField: UITextField) { animateViewMoving(false, moveValue: 100) } func animateViewMoving (up:Bool, moveValue :CGFloat){ var movementDuration:NSTimeInterval = 0.3 var movement:CGFloat = ( up ? -moveValue : moveValue) UIView.beginAnimations( "animateView", context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(movementDuration ) self.view.frame = CGRectOffset(self.view.frame, 0, movement) UIView.commitAnimations() } 

Obtuve esta respuesta de esta fuente UITextField se mueve cuando aparece el keyboard en Swift

Me encanta limpiar el código Swift. Así que aquí está el código más apretado que podría encontrar para mover una vista de text hacia arriba / abajo con el keyboard. Actualmente está trabajando en una aplicación de producción iOS8 / 9 Swift 2.

ACTUALIZACIÓN (marzo de 2016): acabo de ajustar mi código anterior tanto como sea posible. Además, hay un montón de respuestas populares aquí que codifican la altura del keyboard y los parameters de animation. No hay necesidad de eso, por no mencionar que los numbers en estas respuestas no siempre se alinean con los valores reales que veo en mi 6s + iOS9 (altura de keyboard de 226, duración de 0.25 y curva de animation de 7). En cualquier caso, no es casi ningún código adicional para get esos valores directamente del sistema. Vea abajo.

 override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: "animateWithKeyboard:", name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: "animateWithKeyboard:", name: UIKeyboardWillHideNotification, object: nil) } func animateWithKeyboard(notification: NSNotification) { // Based on both Apple's docs and personal experience, // I assume userInfo and its documented keys are available. // If you'd like, you can remove the forced unwrapping and add your own default values. let userInfo = notification.userInfo! let keyboardHeight = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().height let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as! Double let curve = userInfo[UIKeyboardAnimationCurveUserInfoKey] as! UInt let moveUp = (notification.name == UIKeyboardWillShowNotification) // baseContraint is your Auto Layout constraint that pins the // text view to the bottom of the superview. baseConstraint.constant = moveUp ? -keyboardHeight : 0 let options = UIViewAnimationOptions(rawValue: curve << 16) UIView.animateWithDuration(duration, delay: 0, options: options, animations: { self.view.layoutIfNeeded() }, completion: nil ) } 

NOTA: Este código cubre el mayor comentario / caso general. Sin embargo, es posible que se necesite más código para manejar diferentes orientaciones y / o keyboards personalizados. He aquí un artículo en profundidad sobre cómo trabajar con el keyboard iOS. Si necesita manejar cada escenario, esto puede ayudar.

Editar : Recomiendo una solución más fácil y más limpia. Simplemente cambie la class de restricción de espacio inferior a KeyboardLayoutConstraint . Se expandirá automáticamente a la altura del keyboard.


Esta es una versión mejorada de la respuesta de @JosephLord.

Tal como se probó en iOS 8.3 iPad Simulator, Portrait. Xcode6.3 beta4, encontré que su respuesta no funciona cuando el keyboard se esconde porque UIKeyboardFrameEndUserInfoKey es "NSRect: {{0, 1024}, {768, 264}}"; . La altura nunca es 0 .

Esto vuelve a usar el tradicional UIKeyboardWillShowNotification y UIKeyboardWillHideNotification para saber mejor cuándo se esconde el keyboard en lugar de depender de la altura del marco final. UIKeyboardWillShowNotification también se envía cuando se cambia el marco del keyboard para que cubra todos los casos de uso.

  // You have to set this up in storyboard first!. // It's a vertical spacing constraint between view and bottom of superview. @IBOutlet weak var bottomSpacingConstraint: NSLayoutConstraint! override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardNotification:"), name:UIKeyboardWillShowNotification, object: nil); NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardNotification:"), name:UIKeyboardWillHideNotification, object: nil); } deinit { NSNotificationCenter.defaultCenter().removeObserver(self) } func keyboardNotification(notification: NSNotification) { let isShowing = notification.name == UIKeyboardWillShowNotification if let userInfo = notification.userInfo { let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() let endFrameHeight = endFrame?.size.height ?? 0.0 let duration:NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0 let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber let animationCurveRaw = animationCurveRawNSN?.unsignedLongValue ?? UIViewAnimationOptions.CurveEaseInOut.rawValue let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw) self.bottomSpacingConstraint?.constant = isShowing ? endFrameHeight : 0.0 UIView.animateWithDuration(duration, delay: NSTimeInterval(0), options: animationCurve, animations: { self.view.layoutIfNeeded() }, completion: nil) } } 

Esta es una versión mejorada de @JosephLord y la respuesta de @Hlung. Puede aplicarse si tiene tabbar o no. Y restauraría perfectamente la vista que mueve el keyboard a la position original.

 // You have to set this up in storyboard first!. // It's a vertical spacing constraint between view and bottom of superview. @IBOutlet weak var bottomSpacingConstraint: NSLayoutConstraint! override func viewDidLoad() { super.viewDidLoad() // Receive(Get) Notification NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardNotification:", name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardNotification:", name: UIKeyboardWillHideNotification, object: nil) self.originalConstraint = self.keyboardHeightLayoutConstraint?.constant //for original coordinate. } func keyboardNotification(notification: NSNotification) { let isShowing = notification.name == UIKeyboardWillShowNotification var tabbarHeight: CGFloat = 0 if self.tabBarController? != nil { tabbarHeight = self.tabBarController!.tabBar.frame.height } if let userInfo = notification.userInfo { let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() let duration:NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0 let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber let animationCurveRaw = animationCurveRawNSN?.unsignedLongValue ?? UIViewAnimationOptions.CurveEaseInOut.rawValue let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw) self.keyboardHeightLayoutConstraint?.constant = isShowing ? (endFrame!.size.height - tabbarHeight) : self.originalConstraint! UIView.animateWithDuration(duration, delay: NSTimeInterval(0), options: animationCurve, animations: { self.view.layoutIfNeeded() }, completion: nil) } } 
 struct MoveKeyboard { static let KEYBOARD_ANIMATION_DURATION : CGFloat = 0.3 static let MINIMUM_SCROLL_FRACTION : CGFloat = 0.2; static let MAXIMUM_SCROLL_FRACTION : CGFloat = 0.8; static let PORTRAIT_KEYBOARD_HEIGHT : CGFloat = 216; static let LANDSCAPE_KEYBOARD_HEIGHT : CGFloat = 162; } func textFieldDidBeginEditing(textField: UITextField) { let textFieldRect : CGRect = self.view.window!.convertRect(textField.bounds, fromView: textField) let viewRect : CGRect = self.view.window!.convertRect(self.view.bounds, fromView: self.view) let midline : CGFloat = textFieldRect.origin.y + 0.5 * textFieldRect.size.height let numerator : CGFloat = midline - viewRect.origin.y - MoveKeyboard.MINIMUM_SCROLL_FRACTION * viewRect.size.height let denominator : CGFloat = (MoveKeyboard.MAXIMUM_SCROLL_FRACTION - MoveKeyboard.MINIMUM_SCROLL_FRACTION) * viewRect.size.height var heightFraction : CGFloat = numerator / denominator if heightFraction < 0.0 { heightFraction = 0.0 } else if heightFraction > 1.0 { heightFraction = 1.0 } let orientation : UIInterfaceOrientation = UIApplication.shanetworkingApplication().statusBarOrientation if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown) { animateDistance = floor(MoveKeyboard.PORTRAIT_KEYBOARD_HEIGHT * heightFraction) } else { animateDistance = floor(MoveKeyboard.LANDSCAPE_KEYBOARD_HEIGHT * heightFraction) } var viewFrame : CGRect = self.view.frame viewFrame.origin.y -= animateDistance UIView.beginAnimations(nil, context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(NSTimeInterval(MoveKeyboard.KEYBOARD_ANIMATION_DURATION)) self.view.frame = viewFrame UIView.commitAnimations() } func textFieldDidEndEditing(textField: UITextField) { var viewFrame : CGRect = self.view.frame viewFrame.origin.y += animateDistance UIView.beginAnimations(nil, context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(NSTimeInterval(MoveKeyboard.KEYBOARD_ANIMATION_DURATION)) self.view.frame = viewFrame UIView.commitAnimations() } 

Y, por último, ya que estamos utilizando methods de delegates

 func textFieldShouldReturn(textField: UITextField) -> Bool { textField.resignFirstResponder() return true } 

refactonetworking de usar objective-c http://www.cocoawithlove.com/2008/10/sliding-uitextfields-around-to-avoid.html

Otra solución que no depende de la reproducción automática, restricciones o salidas. Lo que necesita es su (s) campo (s) en una vista de desplazamiento.

 override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: "makeSpaceForKeyboard:", name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: "makeSpaceForKeyboard:", name: UIKeyboardWillHideNotification, object: nil) } func makeSpaceForKeyboard(notification: NSNotification) { let info = notification.userInfo! let keyboardHeight:CGFloat = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size.height let duration:Double = info[UIKeyboardAnimationDurationUserInfoKey] as! Double if notification.name == UIKeyboardWillShowNotification { UIView.animateWithDuration(duration, animations: { () -> Void in var frame = self.view.frame frame.size.height = frame.size.height - keyboardHeight self.view.frame = frame }) } else { UIView.animateWithDuration(duration, animations: { () -> Void in var frame = self.view.frame frame.size.height = frame.size.height + keyboardHeight self.view.frame = frame }) } } 

Aquí está mi versión de una solución para Swift 2.2:

Primero regístrate para mostrar / ocultar notifications del keyboard

 NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MessageThreadVC.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MessageThreadVC.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil) 

Luego, en los methods correspondientes para esas notifications, mueva la vista principal hacia arriba o hacia abajo

 func keyboardWillShow(sender: NSNotification) { if let keyboardSize = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() { self.view.frame.origin.y = -keyboardSize.height } } func keyboardWillHide(sender: NSNotification) { self.view.frame.origin.y = 0 } 

El truco está en la parte "keyboardWillShow" que recibe llamadas cada vez que "QuickType Suggestion Bar" se expande o se contrae. Luego, establecemos siempre la coorderada y de la vista principal, que es igual al valor negativo de la altura total del keyboard (con o sin la parte "barra QuickType").

Al final, no te olvides de eliminar a los observadores.

 deinit { NSNotificationCenter.defaultCenter().removeObserver(self) } 

Utilicé este tutorial para mover el campo de text sobre el keyboard. El código está limpio y no es buggy.

http://www.buildsucceeded.com/2014/swift-move-uitextfield-so-keyboard-does-not-hide-it-ios-8-xcode-6-swift/

La siguiente es una solución simple, por la cual el campo de text tiene una restricción que lo vincula con la guía de layout inferior. Simplemente agrega la altura del keyboard a la constante de la restricción.

 // This constraint ties the text field to the bottom layout guide @IBOutlet var textFieldToBottomLayoutGuideConstraint: NSLayoutConstraint! override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name:UIKeyboardWillShowNotification, object: nil); NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name:UIKeyboardWillHideNotification, object: nil); } func keyboardWillShow(sender: NSNotification) { if let keyboardSize = (sender.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() { self.textFieldToBottomLayoutGuideConstraint?.constant += keyboardSize.height } } func keyboardWillHide(sender: NSNotification) { if let keyboardSize = (sender.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() { self.textFieldToBottomLayoutGuideConstraint?.constant -= keyboardSize.height } } 

Bueno, creo que podría ser demasiado tarde pero encontré otra versión simple de la respuesta de Saqib. Estoy usando Autolayout con restricciones. Tengo una pequeña vista dentro de otra vista principal con campos de nombre de usuario y contraseña. En lugar de cambiar la coorderada y de la vista, estoy guardando el valor de la restricción original en una variable y cambiando la constante de la restricción por un valor, y una vez más después de que el keyboard se desactiva, estoy configurando la restricción a la original. De esta forma, evita el problema que tiene la respuesta de Saqib (la vista sigue subiendo y no se detiene). Debajo está mi código …

 override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil); NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil); self.originalConstraint = self.centerYConstraint.constant } func keyboardWillShow(sender: NSNotification) { self.centerYConstraint.constant += 30 } func keyboardWillHide(sender: NSNotification) { self.centerYConstraint.constant = self.originalConstraint } 

Lo he hecho de la siguiente manera:

Esto es útil cuando vista de campo de text es vista

 class AdminLoginViewController: UIViewController, UITextFieldDelegate{ @IBOutlet weak var txtUserName: UITextField! @IBOutlet weak var txtUserPassword: UITextField! @IBOutlet weak var btnAdminLogin: UIButton! private var activeField : UIView? var param:String! var adminUser : Admin? = nil var kbHeight: CGFloat! override func viewDidLoad() { self.addKeyBoardObserver() self.addGestureForHideKeyBoard() } override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } func addGestureForHideKeyBoard() { let tapGesture = UITapGestureRecognizer(target: self, action: Selector("hideKeyboard")) tapGesture.cancelsTouchesInView = false view.addGestureRecognizer(tapGesture) } func hideKeyboard() { self.view.endEditing(true) } func addKeyBoardObserver(){ NSNotificationCenter.defaultCenter().addObserver(self, selector: "willChangeKeyboardFrame:", name:UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: "willChangeKeyboardFrame:", name:UIKeyboardWillHideNotification, object: nil) } func removeObserver(){ NSNotificationCenter.defaultCenter().removeObserver(self) } //MARK:- textfiled Delegate func textFieldShouldBeginEditing(textField: UITextField) -> Bool { activeField = textField return true } func textFieldShouldEndEditing(textField: UITextField) -> Bool { if activeField == textField { activeField = nil } return true } func textFieldShouldReturn(textField: UITextField) -> Bool { if txtUserName == textField { txtUserPassword.becomeFirstResponder() } else if (textField == txtUserPassword) { self.btnAdminLoginAction(nil) } return true; } func willChangeKeyboardFrame(aNotification : NSNotification) { if self.activeField != nil && self.activeField!.isFirstResponder() { if let keyboardSize = (aNotification.userInfo![UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() { let dy = (self.activeField?.superview?.convertRect((self.activeField?.frame)!, toView: view).origin.y)! let height = (self.view.frame.size.height - keyboardSize.size.height) if dy > height { var frame = self.view.frame frame.origin.y = -((dy - height) + (self.activeField?.frame.size.height)! + 20) self.view.frame = frame } } } else { var frame = self.view.frame frame.origin.y = 0 self.view.frame = frame } } } 

La forma más fácil que no requiere ningún código:

  1. Descargue KeyboardLayoutConstraint.swift y agregue (arrastre y suelte) el file a su proyecto, si no está utilizando el marco de animation de Spring ya.
  2. En el guión gráfico, cree una restricción inferior para el object / vista / campo de text, select la restricción (haga doble clic en él) y en el Inspector de identidad, cambie su class de NSLayoutConstraint a KeyboardLayoutConstraint.
  3. ¡Hecho!

El object se moverá automáticamente con el keyboard, en synchronization.

Dicha extensión simple de UIViewController puede usarse

 //MARK: - Observers extension UIViewController { func addObserverForNotification(notificationName: String, actionBlock: (NSNotification) -> Void) { NSNotificationCenter.defaultCenter().addObserverForName(notificationName, object: nil, queue: NSOperationQueue.mainQueue(), usingBlock: actionBlock) } func removeObserver(observer: AnyObject, notificationName: String) { NSNotificationCenter.defaultCenter().removeObserver(observer, name: notificationName, object: nil) } } //MARK: - Keyboard observers extension UIViewController { typealias KeyboardHeightClosure = (CGFloat) -> () func addKeyboardChangeFrameObserver(willShow willShowClosure: KeyboardHeightClosure?, willHide willHideClosure: KeyboardHeightClosure?) { NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardWillChangeFrameNotification, object: nil, queue: NSOperationQueue.mainQueue(), usingBlock: { [weak self](notification) in if let userInfo = notification.userInfo, let frame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue(), let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? Double, let c = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? UInt, let kFrame = self?.view.convertRect(frame, fromView: nil), let kBounds = self?.view.bounds { let animationType = UIViewAnimationOptions(rawValue: c) let kHeight = kFrame.size.height UIView.animateWithDuration(duration, delay: 0, options: animationType, animations: { if CGRectIntersectsRect(kBounds, kFrame) { // keyboard will be shown willShowClosure?(kHeight) } else { // keyboard will be hidden willHideClosure?(kHeight) } }, completion: nil) } else { print("Invalid conditions for UIKeyboardWillChangeFrameNotification") } }) } func removeKeyboardObserver() { removeObserver(self, notificationName: UIKeyboardWillChangeFrameNotification) } } 

Example of usage

 override func viewWillDisappear(animated: Bool) { super.viewDidDisappear(animated) removeKeyboardObserver() } override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) addKeyboardChangeFrameObserver(willShow: { [weak self](height) in //Update constraints here self?.view.setNeedsUpdateConstraints() }, willHide: { [weak self](height) in //Reset constraints here self?.view.setNeedsUpdateConstraints() }) } 
  func registerForKeyboardNotifications() { //Keyboard NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWasShown), name: UIKeyboardDidShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillBeHidden), name: UIKeyboardDidHideNotification, object: nil) } func deregisterFromKeyboardNotifications(){ NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil) } func keyboardWasShown(notification: NSNotification){ let userInfo: NSDictionary = notification.userInfo! let keyboardInfoFrame = userInfo.objectForKey(UIKeyboardFrameEndUserInfoKey)?.CGRectValue() let windowFrame:CGRect = (UIApplication.shanetworkingApplication().keyWindow!.convertRect(self.view.frame, fromView:self.view)) let keyboardFrame = CGRectIntersection(windowFrame, keyboardInfoFrame!) let covenetworkingFrame = UIApplication.shanetworkingApplication().keyWindow!.convertRect(keyboardFrame, toView:self.view) let contentInsets = UIEdgeInsetsMake(0, 0, (covenetworkingFrame.size.height), 0.0) self.scrollViewInAddCase .contentInset = contentInsets; self.scrollViewInAddCase.scrollIndicatorInsets = contentInsets; self.scrollViewInAddCase.contentSize = CGSizeMake((self.scrollViewInAddCase.contentSize.width), (self.scrollViewInAddCase.contentSize.height)) } /** this method will fire when keyboard was hidden - parameter notification: contains keyboard details */ func keyboardWillBeHidden (notification: NSNotification) { self.scrollViewInAddCase.contentInset = UIEdgeInsetsZero self.scrollViewInAddCase.scrollIndicatorInsets = UIEdgeInsetsZero } 

I created a Swift 3 protocol to handle the keyboard appearance / disappearance

 import Foundation protocol KeyboardHandler: class { var bottomConstraint: NSLayoutConstraint! { get set } func keyboardWillShow(_ notification: Notification) func keyboardWillHide(_ notification: Notification) func startObservingKeyboardChanges() func stopObservingKeyboardChanges() } extension KeyboardHandler where Self: UIViewController { func startObservingKeyboardChanges() { // NotificationCenter observers NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillShow, object: nil, queue: nil) { (notification) in self.keyboardWillShow(notification) } // Deal with rotations NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil, queue: nil) { (notification) in self.keyboardWillShow(notification) } // Deal with keyboard change (emoji, numerical, etc.) NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextInputCurrentInputModeDidChange, object: nil, queue: nil) { (notification) in self.keyboardWillShow(notification) } NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillHide, object: nil, queue: nil) { (notification) in self.keyboardWillHide(notification) } } func keyboardWillShow(_ notification: Notification) { let verticalPadding: CGFloat = 20 // Padding between the bottom of the view and the top of the keyboard guard let value = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return } let keyboardHeight = value.cgRectValue.height // Here you could have more complex rules, like checking if the textField currently selected is actually covenetworking by the keyboard, but that's out of this scope. self.bottomConstraint.constant = keyboardHeight + verticalPadding UIView.animate(withDuration: 0.1, animations: { () -> Void in self.view.layoutIfNeeded() }) } func keyboardWillHide(_ notification: Notification) { self.bottomConstraint.constant = 0 UIView.animate(withDuration: 0.1, animations: { () -> Void in self.view.layoutIfNeeded() }) } func stopObservingKeyboardChanges() { NotificationCenter.default.removeObserver(self) } } 

Then, to implement it in a UIViewController, do the following:

  • let the viewController conform to this protocol :

     class FormMailVC: UIViewControlle, KeyboardHandler { 
  • start observing keyboard changes in viewWillAppear:

     // MARK: - View controller life cycle override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) startObservingKeyboardChanges() } 
  • stop observing keyboard changes in viewWillDisappear:

     override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) stopObservingKeyboardChanges() } 
  • create an IBOutlet for the bottom constraint from the storyboard:

     // NSLayoutConstraints @IBOutlet weak var bottomConstraint: NSLayoutConstraint! 

    (I recommend having all of your UI embedded inside a "contentView", and linking to this property the bottom constraint from this contentView to the bottom layout guide) Content view bottom constraint

  • change the constraint priority of the top constraint to 250 (low)

Content view top constraint

This is to let the whole content view slide upwards when the keyboard appears. The priority must be lower than any other constraint priority in the subviews, including content hugging priorities / content compression resistance priorities.

  • Make sure that your Autolayout has enough constraints to determine how the contentView should slide up.

You may have to add a "greater than equal" constraint for this: "greater than equal" constraint

And here you go! Without keyboard

With keyboard

I have done in following manner :

 class SignInController: UIViewController , UITextFieldDelegate { @IBOutlet weak var scrollView: UIScrollView! // outlet declartion @IBOutlet weak var signInTextView: UITextField! var kbHeight: CGFloat! /** * * @method viewDidLoad * */ override func viewDidLoad() { super.viewDidLoad() self.signInTextView.delegate = self }// end viewDidLoad /** * * @method viewWillAppear * */ override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil) }// end viewWillAppear /** * * @method viewDidAppear * */ override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) }// end viewDidAppear /** * * @method viewWillDisappear * */ override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) NSNotificationCenter.defaultCenter().removeObserver(self) } /** * * @method textFieldShouldReturn * retun the keyboard value * */ // MARK - func textFieldShouldReturn(textField: UITextField) -> Bool { signInTextView.resignFirstResponder() return true; }// end textFieldShouldReturn // MARK - keyboardWillShow func keyboardWillShow(notification: NSNotification) { if let userInfo = notification.userInfo { if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() { kbHeight = keyboardSize.height self.animateTextField(true) } } }// end keyboardWillShow // MARK - keyboardWillHide func keyboardWillHide(notification: NSNotification) { self.animateTextField(false) }// end keyboardWillHide // MARK - animateTextField func animateTextField(up: Bool) { var movement = (up ? -kbHeight : kbHeight) UIView.animateWithDuration(0.3, animations: { self.view.frame = CGRectOffset(self.view.frame, 0, movement) }) }// end animateTextField /** * * @method didReceiveMemoryWarning * */ override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. }// end didReceiveMemoryWarning }// end SignInController 

You can use this library and just one line of code in appDidFinishedLaunching and u are done..

 func application(application: UIApplication,didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { IQKeyboardManager.shanetworkingManager().enable = true return true } 

IQKeyboardManager – adjust view whenever keyboard appear link – https://github.com/hackiftekhar/IQKeyboardManager

If you are like me who has tried all the above solutions and still your problem is not solved, I have a got a great solution for you that works like a charm. First I want clarify few things about some of solutions mentioned above.

  1. In my case IQkeyboardmanager was working only when there is no auto layout applied on the elements, if it is applied then IQkeyboard manager will not work the way we think.
  2. Same thing with upward movement of self.view.
  3. i have wriiten a objective c header with a swift support for pushing UITexfield upward when user clicks on it, solving the problem of keyboard covering the UITextfield : https://github.com/coolvasanth/smart_keyboard .
  4. One who has An intermediate or higher level in iOS app development can easily understand the repository and implement it. Todo lo mejor

If you don't mind using Objective-C library in your Swift project, perhaps you can use this helper . It comes with an example for Swift usage too.

I modified @Simpa solution a little bit………

 override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("makeSpaceForKeyboard:"), name:UIKeyboardWillShowNotification, object: nil); NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("makeSpaceForKeyboard:"), name:UIKeyboardWillHideNotification, object: nil); } deinit{ NSNotificationCenter.defaultCenter().removeObserver(self) } var keyboardIsVisible = false override func makeSpaceForKeyboard(notification: NSNotification) { let info = notification.userInfo! let keyboardHeight:CGFloat = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size.height let duration:Double = info[UIKeyboardAnimationDurationUserInfoKey] as! Double if notification.name == UIKeyboardWillShowNotification && keyboardIsVisible == false{ keyboardIsVisible = true UIView.animateWithDuration(duration, animations: { () -> Void in var frame = self.view.frame frame.size.height = frame.size.height - keyboardHeight self.view.frame = frame }) } else if keyboardIsVisible == true && notification.name == UIKeyboardWillShowNotification{ }else { keyboardIsVisible = false UIView.animateWithDuration(duration, animations: { () -> Void in var frame = self.view.frame frame.size.height = frame.size.height + keyboardHeight self.view.frame = frame }) } } 

None of them worked for and I ended up using content insets to move my view up when the keyboard appears.

Note: I was using a UITableView

Referenced solution @ keyboard-content-offset which was entirely written in objective C, the below solution is clean Swift.

Add the notification observer @ viewDidLoad()

 NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(yourClass.keyboardWillBeShown), name:UIKeyboardWillShowNotification, object: nil); NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(yourClass.keyboardWillBeHidden), name:UIKeyboardWillHideNotification, object: nil); 

To get the keyboard size, we first get the userInfo dictionary from the notification object, which stores any additional objects that our receiver might use.

From that dictionary we can get the CGRect object describing the keyboard's frame by using the key UIKeyboardFrameBeginUserInfoKey.

Apply the content inset for the table view @ keyboardWillBeShown method,

 func keyboardWillBeShown(sender: NSNotification) { // Move the table view if let keyboardSize = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() { let contentInsets = UIEdgeInsetsMake(0.0, 0.0, (keyboardSize.height), 0.0); yourTableView.contentInset = contentInsets; yourTableView.scrollIndicatorInsets = contentInsets; } } 

Restore the view @ keyboardWillBeHidden method

 func keyboardWillBeHidden(sender: NSNotification) { // Moving back the table view back to the default position yourTableView.contentInset = UIEdgeInsetsZero; yourTableView.scrollIndicatorInsets = UIEdgeInsetsZero; } 

If you want to keep the device orientation also into consideration, use conditional statements to tailor the code to your needs.

 // Portrait UIEdgeInsetsMake(0.0, 0.0, (keyboardSize.height), 0.0); // Landscape UIEdgeInsetsMake(0.0, 0.0, (keyboardSize.width), 0.0); 
 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } func keyboardWillShow(_ notification:Notification) { if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue { tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0) } } func keyboardWillHide(_ notification:Notification) { if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue { tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0) } } [enter image description here][1]