The problem: UITextView
silently changes it\'s contentSize
in some situations.
The simplest case textView with large text and keyboard. Just ad
Looks like the problem is in default layoutManager of UITextView
. I've decided to subclass it and see, where and why re-layout being initiated. But simple creation of NSLayoutManager
with default settings solved the problem.
Here is code (not perfect) from my demo project (see in question). The _textView
there was an outlet, so I remove it from superview. This code is placed in - viewDidLoad
:
NSTextStorage* textStorage = [[NSTextStorage alloc] initWithString:_textView.text];
NSLayoutManager* layoutManager = [NSLayoutManager new];
[textStorage addLayoutManager:layoutManager];
_textContainer = [[NSTextContainer alloc] initWithSize:self.view.bounds.size];
[layoutManager addTextContainer:_textContainer];
[_textView removeFromSuperview]; // remove original textView
_textView = [[MyTextView alloc] initWithFrame:self.view.bounds
textContainer:_textContainer];
[self.view addSubview:_textView];
MyTextView
here is a subclass of UITextView
, see question for details.
For more info see:
I met a similar situation as urs. Mine shows with a different bug but due to the same reason: the contentSize property is silently changed by iOS7 incorrectly. Here is how I work around it. Its kinda a ugly fix. Whenever I need to use textView.contentSize, I calculate it by myself.
-(CGSize)sizeOfText:(NSString *)textToMesure widthOfTextView:(CGFloat)width withFont:(UIFont*)font
{
CGSize size = [textToMesure sizeWithFont:font constrainedToSize:CGSizeMake(width-20.0, FLT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
return size;
}
then you can just call this function to get the size:
CGSize cont_size = [self sizeOfText:self.text widthOfTextView:self.frame.size.width withFont:[UIFont systemFontOfSize:15]];
then, don't do the following:
self.contentSize = cont_size;// it causes iOS halt occasionally.
so, just use cont_size directly. I believe it's bug in iOS7 for now. Hopefully apple will fix it soon. Hope this is helpful.
Seems the bug in iOS7. At the time of input text content area behavior is wired in iOS7, It works fine with lower iOS7 version.
I have added below delegate method of UITextView to resolved this issue :
- (void)textViewDidChange:(UITextView *)textView {
CGRect line = [textView caretRectForPosition:
textView.selectedTextRange.start];
CGFloat overflow = line.origin.y + line.size.height
- ( textView.contentOffset.y + textView.bounds.size.height
- textView.contentInset.bottom - textView.contentInset.top );
if ( overflow > 0 ) {
// We are at the bottom of the visible text and introduced a line feed, scroll down (iOS 7 does not do it)
// Scroll caret to visible area
CGPoint offset = textView.contentOffset;
offset.y += overflow + 7; // leave 7 pixels margin
// Cannot animate with setContentOffset:animated: or caret will not appear
[UIView animateWithDuration:.2 animations:^{
[textView setContentOffset:offset];
}];
}