Simply calling UITextView `sizeThatFits:` causes g

2019-05-08 05:41发布

问题:

I find that in iOS 8 using UITextView sizeThatFits: causes glitchy scrolling behavior. The Text View is constantly scrolling away from the line you are typing on. It seems to be scrolling to the top of the view and then back again.

If it matters, the view is set as an inputAccessoryView.

Via the keyboard I'll type: 1 return 2 return 3 return 4

The TextView the moment before I type 4:

In the delegate method I call sizeThatFits:.

- (void)textViewDidChange:(UITextView *)textView {
    [textView sizeThatFits:CGSizeMake(100, 100)];
}

TextView scrolls up to the top. Input happens below the view. Jittery, glitchy scrolling movement up to the top and then back to your line as you type. Input occurs under the keyboard. Extremely annoying.

If I comment out the line:

//[textView sizeThatFits:CGSizeMake(100, 100)];

Now when I type 4 we have nice, smooth typing on the last line:

The UIScrollView sizeThatFits: docs state:

This method does not resize the receiver.

So I'm confused why this would have any effect on the scrolling/input of the textfield.

Is there any way to avoid this glitchy scrolling?

How can you calculate the "height that fits" for a Text View without hitting this bug?

回答1:

I had the exact same problem and it took me 5 hours to solve this nasty apple bug, I wish I could send them an invoice! What I end up doing was creating a copy of my original UItextView:

self.textViewCopy = [[UITextView alloc] initWithFrame:self.textView.frame];
[self.textViewCopy setFont:self.textView.font];

And don't add it as a subview.

Then instead call the sizeThatFits on the copy (which will screw up the copy which we don't care about and gets us the information we need):

[self.textViewCopy setText:self.textView.text];
CGSize size = [self.textViewCopy sizeThatFits:CGSizeMake(fixedWidth, CGFLOAT_MAX)];


回答2:

Using the NSString method sizeWithFont:constrainedToSize: on the text within the UITextView seems to provide a performant alternative to sizeThatFits:.

CGSize preferredSize = [textView.text sizeWithFont:textView.font constrainedToSize:CGSizeMake(CGRectGetWidth(textView.bounds), 200.0)];

It's possible that sizeThatFits: is using sizeWithFont:constrainedToSize: under the hood. Regardless, the iOS glitchy scrolling bug is not reproduced when using the NSString method.