UITextView contentSize更改和iOS7中的NSLayoutManager [英] UITextView contentSize changes and NSLayoutManager in iOS7

查看:164
本文介绍了UITextView contentSize更改和iOS7中的NSLayoutManager的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题: 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆