9

問題:状況によっては、UITextView静かに変更さcontentSizeれます。

大きなテキストとキーボードを備えた最も単純なケースの textView。UITextView アウトレットを追加して、次のように設定する- 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}

の動作はUITextViewiOS7 で大幅に変更されたようです。そして今壊れているものもあります。

さらに発見するlayoutManagerと、textView の新しいプロパティも変更されることがわかりました。ログに興味深い情報がいくつかあります:

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}containsの次の行Layout tree contents: ..., 2127 laid glyphs, 51 laid line fragments。そのため、ある種の自動レイアウトがキーボード ショーで textView を再レイアウトしようとし、レイアウトがまだ完了していなくても contentSize を変更するようです。また、キーボードの表示/非表示の間で textView が変更されていなくても実行されます。

問題は、contentSize の変更を防ぐ方法です。

4

3 に答える 3

1

iOS7のバグのようです。テキスト入力時のコンテンツエリアの挙動はiOS7で有線化されていますが、iOS7以下のバージョンでは問題なく動作します。

この問題を解決するために、以下の UITextView のデリゲート メソッドを追加しました。

- (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];
    }];
}
于 2013-10-23T12:36:38.933 に答える