UITextView contentSize更改和iOS7中的NSLayoutManager [英] UITextView contentSize changes and NSLayoutManager in iOS7
问题描述
问题: UITextView
在某些情况下默默地更改它的 contentSize
。
The problem: UITextView
silently changes it's contentSize
in some situations.
最简单的案例textView,带有大文本和键盘。只需添加UITextView插座并将 - viewDidLoad
设置为:
The simplest case textView with large text and keyboard. Just add UITextView outlet and set - viewDidLoad
as:
- (void)viewDidLoad {
[super viewDidLoad];
// expand default "Lorem..."
_textView.text = [NSString stringWithFormat:@"1%@\n\n2%@\n\n3%@\n\n4%@\n\n5", _textView.text, _textView.text, _textView.text, _textView.text];
_textView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
_textView.contentInset = UIEdgeInsetsMake(0, 0, 216, 0);
}
现在显示和隐藏键盘会导致文本跳转。
Now showing and hiding keyboard will cause text jumps in some cases.
我找到了按子类 UITextView
跳转的原因。我的子类中唯一的方法是:
I've found the reason of jumping by subclass UITextView
. The only method in my subclass is:
- (void)setContentSize:(CGSize)contentSize {
NSLog(@"CS: %@", NSStringFromCGSize(contentSize));
[super setContentSize:contentSize];
}
它显示 contentSize
缩小和扩展键盘隐藏。这样的事情:
And it show contentSize
shrinks and expands on keyboard hide. Something like this:
013-09-16 14:40:27.305 textView-bug2[11087:a0b] CS: {320, 651}
2013-09-16 14:40:27.313 textView-bug2[11087:a0b] CS: {320, 885}
2013-09-16 14:40:27.318 textView-bug2[11087:a0b] CS: {320, 902}
看起来像的行为UITextView
在iOS7中发生了很大变化。现在有些事情已经破裂。
Looks like behavior of UITextView
was changed a lot in iOS7. And some things are broken now.
进一步发现我发现我的textView的新 layoutManager
属性也发生了变化。现在日志中有一些有趣的信息:
Discovering further I've found that new layoutManager
property of my textView changes too. There some interesting info in log now:
2013-09-16 14:41:59.352 textView-bug2[11115:a0b] CS: {320, 668}
<NSLayoutManager: 0x899e800>
1 containers, text backing has 2129 characters
Currently holding 2129 glyphs.
Glyph tree contents: 2129 characters, 2129 glyphs, 3 nodes, 96 node bytes, 5440 storage bytes, 5536 total bytes, 2.60 bytes per character, 2.60 bytes per glyph
Layout tree contents: 2129 characters, 2129 glyphs, 532 laid glyphs, 13 laid line fragments, 4 nodes, 128 node bytes, 1048 storage bytes, 1176 total bytes, 0.55 bytes per character, 0.55 bytes per glyph, 40.92 laid glyphs per laid line fragment, 90.46 bytes per laid line fragment
下一行包含contentSize = {320,885}
包含布局树内容:...,2127个已放置的字形,51个已放置的行片段
。所以看起来某种autolayout试图在键盘上重新布局textView并改变contentSize,即使布局还没有完成。即使我的textView在键盘显示/隐藏之间没有变化也会运行。
And next line with contentSize = {320, 885}
contains Layout tree contents: ..., 2127 laid glyphs, 51 laid line fragments
. So it looks like some kind of autolayout tries to re-layout textView on keyboard show and changes contentSize even if layout is not finished yet. And it runs even if my textView is not changes between keyboard show/hide.
问题是:如何防止更改contentSize?
推荐答案
看起来问题出在 UITextView
的默认layoutManager中。我已经决定对它进行子类化,并查看重新布局的启动位置和原因。但是使用默认设置简单创建 NSLayoutManager
解决了这个问题。
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.
以下是我演示的代码(不完美)项目(见问题)。 _textView
有一个插座,所以我从superview中删除它。此代码位于 - viewDidLoad
:
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
这里是一个子类 UITextView
,有关详细信息,请参阅问题。
MyTextView
here is a subclass of UITextView
, see question for details.
有关详细信息,请参阅:
For more info see:
- About Text Handling in iOS
- Using Text Kit to Draw and Manage Text
- NSLayoutManager Class Reference for iOS
这篇关于UITextView contentSize更改和iOS7中的NSLayoutManager的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!