UITextField文本跳转iOS 9

上一个问题的链接: UITextField文本跳转

简而言之:我有一个带有2个UITextField元素的ViewController 。 当loginField是firstResponder时,之后

 self.passwordField.becomeFirstResponder() 

登录字段中的文本跳转到左上角和后面。 而且更奇怪的是:这个故障只是第一次重现,然后你需要重新创建ViewController来观察这种行为

这是故障的videohttp://tinypic.com/player.php?v=6nsemw%3E&s=8#.VgVb3cuqpHx

我最终得到了这个(不适用于iOS 9):

 func textFieldShouldReturn(textField: UITextField) -> Bool { if textField === self.loginField { self.loginField.resignFirstResponder() // Shitty workaround. Hi, Apple! self.loginField.setNeedsLayout() self.loginField.layoutIfNeeded() self.passwordField.becomeFirstResponder() return false } return true } 

是否有人被这个错误所困扰? 有什么建议么?

键盘通知处理程序

我的主视图是UIScrollView,我将底部空间更改为superview,因此即使键盘显示,用户也可以滚动所有内容

 func keyboardWillShow(notification : NSNotification) { let keyboardInfo = notification.userInfo! let keyboardFrame = keyboardInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue let animDuration = keyboardInfo[UIKeyboardAnimationDurationUserInfoKey]!.doubleValue! UIView.animateWithDuration(animDuration, animations: { self.scrollViewBottom.constant = keyboardFrame.height self.view.layoutIfNeeded() let offsetY = CGRectGetMaxY(self.loginButton.frame) + 10 - self.scrollView.frame.height if offsetY > 0 { self.scrollView.contentOffset = CGPointMake(0, offsetY) } }) } func keyboardWillHide(notification : NSNotification) { self.scrollViewBottom.constant = 0 self.view.layoutIfNeeded() } 

当我在iOS7中发现键盘通知时,8和9非常不同。 因此,在iOS 9中,即使键盘不显示/隐藏,也会在更改firstResponder时发送通知。 此外,当我通过点击textField更改firstResponder(而不是在我的代码处理的键盘上点击Next)时,只有KeyboardWillShow通知而没有KeyboardWillHide。 至于我,userInfo有一些垃圾框架值,这里是使用下一个按钮更改第一响应者时的日志(工作正常,没有毛刺):

2015-10-07 12:54:13.870 keyboardWillHide:[UIKeyboardFrameBeginUserInfoKey:NSRect:{{0,352},{320,216}},UIKeyboardCenterBeginUserInfoKey:NSPoint:{160,460},UIKeyboardFrameEndUserInfoKey:NSRect:{{0,568 },{320,216}},UIKeyboardCenterEndUserInfoKey:NSPoint:{160,676},UIKeyboardAnimationDurationUserInfoKey:0.25,UIKeyboardIsLocalUserInfoKey:1,UIKeyboardBoundsUserInfoKey:NSRect:{{0,0},{320,216}},UIKeyboardAnimationCurveUserInfoKey:7] 2015 -10-07 12:54:13.896 keyboardWillShow:[UIKeyboardFrameBeginUserInfoKey:NSRect:{{0,352},{320,216}},UIKeyboardCenterBeginUserInfoKey:NSPoint:{160,460},UIKeyboardFrameEndUserInfoKey:NSRect:{{0,352} ,{320,216}},UIKeyboardCenterEndUserInfoKey:NSPoint:{160,460},UIKeyboardAnimationDurationUserInfoKey:0.25,UIKeyboardIsLocalUserInfoKey:1,UIKeyboardBoundsUserInfoKey:NSRect:{{0,0},{320,216}},UIKeyboardAnimationCurveUserInfoKey:7]

当我点击第二个textField时,这是日志:

2015-10-07 12:55:13.879 keyboardWillShow:[UIKeyboardFrameBeginUserInfoKey:NSRect:{{0,352},{320,216}},UIKeyboardCenterBeginUserInfoKey:NSPoint:{160,460},UIKeyboardFrameEndUserInfoKey:NSRect:{{0,352 },{320,216}},UIKeyboardCenterEndUserInfoKey:NSPoint:{160,460},
UIKeyboardAnimationDurationUserInfoKey:0.25,UIKeyboardIsLocalUserInfoKey:1,UIKeyboardBoundsUserInfoKey:NSRect:{{0,0},{320,216}},UIKeyboardAnimationCurveUserInfoKey:7]

解析度

我发现我有另一个键盘控制器接收键盘通知并制作一些动画。 这就是问题所在

根据您编辑的问题,当您点击键盘上的下一个按钮时,我可以看到这一点:

  1. 您正在调用resignFirstResponder()然后调用becomeFirstResponder() 。 这会调用keyboardWillHide通知,然后调用keyboardWillShow通知
  2. keyboardWillHide你有self.view.layoutIfNeeded() ,它可以在没有动画的情况下布局视图(和子视图 – 文本字段)。

因此,文本字段布局是“固定的”,当您在keyboardWillShow执行动画时,textfield中的文本不再“跳”,因为您在keyboardWillHide进行了布局。

但是,当您只是点击另一个文本字段时,只调用keyboardWillShow ,布局不会在文本字段中“固定”,当您为视图设置动画时,文本会执行“跳转”动画。

这就是为什么当你点击键盘上的下一个时它不会跳转,但是当你点击另一个文本字段时它会跳转。

所以我建议将其更改为:

 func textFieldShouldReturn(textField: UITextField) -> Bool { if textField === self.loginField { self.passwordField.becomeFirstResponder() return false } return true } func keyboardWillShow(notification : NSNotification) { let keyboardInfo = notification.userInfo! let keyboardFrame = keyboardInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue let animDuration = keyboardInfo[UIKeyboardAnimationDurationUserInfoKey]!.doubleValue! self.loginField.layoutIfNeeded() self.passwordField.layoutIfNeeded() if keyboardFrame.height != self.scrollViewBottom.constant { UIView.animateWithDuration(animDuration, animations: { self.scrollViewBottom.constant = keyboardFrame.height self.view.layoutIfNeeded() let offsetY = CGRectGetMaxY(self.loginButton.frame) + 10 - self.scrollView.frame.height if offsetY > 0 { self.scrollView.contentOffset = CGPointMake(0, offsetY) } }) } } 

Tnx到haluzak :

 func textFieldShouldReturn(textField: UITextField) -> Bool { if textField === self.loginField { self.passwordField.becomeFirstResponder() return false } return true } func keyboardWillShow(notification : NSNotification) { let keyboardInfo = notification.userInfo! let keyboardFrame = keyboardInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue let animDuration = keyboardInfo[UIKeyboardAnimationDurationUserInfoKey]!.doubleValue! UIView.performWithoutAnimation({ self.loginField.layoutIfNeeded() self.passwordField.layoutIfNeeded() }) if keyboardFrame.height != self.scrollViewBottom.constant { UIView.animateWithDuration(animDuration, animations: { self.scrollViewBottom.constant = keyboardFrame.height self.view.layoutIfNeeded() let offsetY = CGRectGetMaxY(self.loginButton.frame) + 10 - self.scrollView.frame.height if offsetY > 0 { self.scrollView.contentOffset = CGPointMake(0, offsetY) } }) } } 

当我试图改变第一响应者时,我遇到了同样的问题。 这个问题有一个更好的解决方案。 只需实现UITextField子类并在地方使用,您可以在其中设置文本字段的动画(键盘,首先响应切换等)。

 @interface UITextFieldFixed : UITextField @end @implementation UITextFieldFixed - (BOOL)resignFirstResponder { BOOL result = [super resignFirstResponder]; [self setNeedsLayout]; [self layoutIfNeeded]; return result; } @end 

有关问题的更多信息: https : //github.com/foundry/UITextFieldBug

复制并粘贴Swift3 …

 class UITextFieldFixed: UITextField { override func resignFirstResponder() -> Bool { let r = super.resignFirstResponder() self.setNeedsLayout() self.layoutIfNeeded() return r } } 

将此代码放入键盘将显示通知,在您进行任何动画之前:

 UIView.performWithoutAnimation({ self.yourTextField1.layoutIfNeeded() self.yourTextField2.layoutIfNeeded() //etc. }) 

这是为了停止跳转文本而需要编写的简单代码。 这对我有用。

func textFieldDidEndEditing(_ textField: UITextField) { // Workaround for the jumping text bug. textField.resignFirstResponder() textField.layoutIfNeeded() }