问题:UITextView
在某些情况下悄悄地改变了它的 contentSize
。
最简单的情况是带有大文本和键盘的 textView。只需添加 UITextView socket 并将 - viewDidLoad
设置为:
- (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);
}
现在显示和隐藏键盘在某些情况下会导致文本跳转。
我找到了子类 UITextView
跳转的原因。我的子类中唯一的方法是:
- (void)setContentSize:(CGSize)contentSize {
NSLog(@"CS: %@", NSStringFromCGSize(contentSize));
[super setContentSize:contentSize];
}
它显示 contentSize
在键盘隐藏处收缩和扩展。像这样:
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 中发生了很大变化。现在有些东西坏了。
进一步发现,我发现我的 textView 的新 layoutManager
属性也发生了变化。现在日志中有一些有趣的信息:
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}
的下一行包含Layout tree contents: ..., 2127 layed glyphs, 51 layed line fragments
。所以看起来某种自动布局试图在键盘显示上重新布局 textView 并更改 contentSize 即使布局尚未完成。即使我的 textView 在键盘显示/隐藏之间没有变化,它也会运行。
问题是:如何防止contentSize变化?
最佳答案
看起来问题出在 UITextView
的默认布局管理器中。我决定将它子类化,看看在哪里以及为什么开始重新布局。但是使用默认设置简单地创建 NSLayoutManager
就解决了这个问题。
这是我的演示项目(见问题)中的代码(不完美)。 _textView
有一个 socket ,所以我将它从 superview 中删除。这段代码放在-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
的子类,详见问题。
有关详细信息,请参阅:
关于ios - iOS7 中UITextView contentSize 的变化和NSLayoutManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18826199/