3

I am running on iOS 9, XCode 7 GM. I have a class that extends UITextField (CustomOffsetTextField) and provides support for custom text positioning like so:

override func textRectForBounds(bounds: CGRect) -> CGRect {
    return CGRectOffset(bounds, textOffset.x + leftViewOffset, textOffset.y)
}

override func placeholderRectForBounds(bounds: CGRect) -> CGRect {
    return CGRectOffset(bounds, textOffset.x + leftViewOffset, textOffset.y)
}

override func editingRectForBounds(bounds: CGRect) -> CGRect {
    return CGRectOffset(bounds, textOffset.x + leftViewOffset, textOffset.y)
}

leftViewOffset is the width of the text field's leftView, if one exists. textOffset is a CGPoint that defines custom x and y offsets to apply to the text rects.

My issue is occurring on my sign in view. I have 2 instances of my CustomOffsetTextField - one for the user's e-mail and one for their password.

On first load of the view controller, if I enter text into one field and then tap into the other field, that text will jump back to position 0,0 in its text field briefly before jumping back to the position that is defined by textRectForBounds. Some basic print debugging verifies that these functions are always returning the values that I expect them to.

After this initial hiccup, the text field then behaves as I would expect it to. This issue only occurs one time in each text field after the view controller loads. After that, I can tap back and forth between the fields as much as I want without it happening again.

Has anyone seen similar issues with UITextField in iOS 9? If so, were you able to find a fix?

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Reid Conner
  • 223
  • 1
  • 3
  • 7
  • I was having a similar issue, except that the text of my "first" UITextField was being momentarily cleared whenever I tapped on the "second" UITextField (this happens only briefly and was quickly replaced by the correct text that was provided by the user). After implementing the solution proposed by @Jesse, it is no longer a problem. I am still experiencing an issue related to a UITextField with secureTextEntry set to YES - that is, when it becomes first responder the editingRectForBounds is several points below what it should be (it is not vertically aligned within the UITextField's bounds). – Drew Burnett Sep 20 '15 at 22:54
  • Are you using custom fonts? Certain custom fonts have been known to cause issues w/ secureTextEntry. We had to jump through some hoops in our own app to get around this. If you are allowing the user to show/hide the text in that field, try applying the system font right before setting secureTextEntry to YES and then reapplying your custom font right after setting it back to NO. This worked for us. – Reid Conner Sep 21 '15 at 18:54

1 Answers1

6

In iOS 9 an extra UIKeyboardWillShowNotification notification is sent whenever you tap between the text fields. If you have a call to [self.view layoutIfNeeded] in the notification callback it will cause the jump.

// Animate
[UIView beginAnimations:@"keyboardDidShowAnimations" context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
[self.view layoutIfNeeded];
[UIView commitAnimations];

It's related to this: https://forums.developer.apple.com/message/53905#53905

If you're testing in the simulator without the software keyboard, you'll get an extra UIKeyboardWillHideNotification instead which will likely cause the same issue if you have a layoutIfNeeded call in that notification callback as well.

I resolved this by putting checks at the top of the callbacks to ensure that I really needed to animate/update constraints.

- (void)keyboardWillShow:(NSNotification *)note {
    BOOL shouldAnimate = self.someConstraint.constant != kMinimumSize;
    if (shouldAnimate) {
...

- (void)keyboardWillHide:(NSNotification *)note {
    BOOL shouldAnimate = self.someConstraint.constant == kMinimumSize;
    if (shouldAnimate) {
...

Update: This won't necessarily work properly with 3rd party keyboards which call the notification methods multiple times. See https://stackoverflow.com/a/26004605.

Community
  • 1
  • 1
Jesse
  • 1,667
  • 12
  • 16