2016-09-20 4 views
0

私は "ローリングログ"と呼ばれるものを表示しているNSTextViewを持っています。新しいAttributedStringはちょうど約毎秒追加されています。私がしたいのは、文字列が特定の長さ、または特定の数の行に当たった場合、NSTextViewの先頭から切り捨てることです。これは、表示されたログが1トンのメモリを消費しないようにするためです。自動スクロールのテキストの長さを制限するNSTextView

これについてはどうすればよいですか?私はいくつかのコードを持っていますが、それは私が期待するように、特に自動スクロールの周りに動作するようには見えません。

期待される動作:

  • 必要に応じて引き出し線を取り外します(これは線や文字の数である場合、私は本当に最も簡単な方、気にしません)。
  • ビューがスクロールアップされていない場合は、自動的にスクロールします(ユーザーが現在スクロールしている場合は、スクロールしてもスクロールしません)。

コード:

- (void)append:(TextTag*)text toTextView:(MyNSTextView *) textView { 

    dispatch_async(dispatch_get_main_queue(), ^{ 

     NSAttributedString *attr = [self stringFromTag:text]; 

     NSScroller *scroller = [[textView enclosingScrollView] verticalScroller]; 

     double autoScrollToleranceLineCount = 3.0; 

     NSUInteger lines = [self countLines:[textView string]]; 
     double scrolled = [scroller doubleValue]; 
     double scrollDiff = 1.0 - scrolled; 
     double percentScrolled = autoScrollToleranceLineCount/lines; 

     BOOL shouldScrollToBottom = scrollDiff <= percentScrolled; 

     [textView.textStorage beginEditing]; 

     if (lines >= 10000) { 
      NSRange removeRange = [self getRemovalRange:textView.string]; 
      [textView.textStorage deleteCharactersInRange:removeRange]; 
     } 

     [[textView textStorage] appendAttributedString:attr]; 

     [textView.textStorage endEditing]; 

     if(shouldScrollToBottom) { 
      [textView scrollRangeToVisible:NSMakeRange([[textView string] length], 0)]; 
     } 
    }); 
} 

- (NSRange)getRemovalRange:(NSString *)s { 

    NSUInteger numberOfLines, index, stringLength = [s length]; 

    for (index = 0, numberOfLines = 0; index < stringLength; 
     numberOfLines++) { 
     index = NSMaxRange([s lineRangeForRange:NSMakeRange(index, 0)]); 
     if (numberOfLines >= 100) { 
      break; 
     } 
    } 

    return NSMakeRange(0, index); 
} 

- (NSUInteger) countLines:(NSString *)s { 

    NSUInteger numberOfLines, index, stringLength = [s length]; 

    for (index = 0, numberOfLines = 0; index < stringLength; 
     numberOfLines++) { 
     index = NSMaxRange([s lineRangeForRange:NSMakeRange(index, 0)]); 
    } 
    return numberOfLines; 
} 
+0

私は何か似たようなことをしました。スクロールは 'self performSelector:@selector(scrollProgressTextViewToEnd)withObject:nil afterDelay:0];'のようなrunloopの次の反復で実行されます。 – Willeke

+0

@Willeke最初に行って、それは動作しているようです!それを一日中混乱させてしまいますが、それを答えとして追加して、私はあなたに信用を与えることができますか? –

+0

それを数時間試した後も、時にはスクロールしないようです。 =/ –

答えて

0

ここで私は(数年前、試行錯誤)やったことです。

- (void)scrollProgressTextViewToEnd 
{ 
    if ([progressTextView isFlipped]) 
     [progressTextView scrollPoint:NSMakePoint(0.0, NSMaxY([progressTextView frame]) - NSHeight([progressTextView visibleRect]))]; 
    else 
     [progressTextView scrollPoint:NSMakePoint(0.0, 0.0)]; 
} 

- (void)appendToProgressText:(NSString *)theString bold:(BOOL)theBold 
{ 
    [progressTextView.textStorage beginEditing]; 
    [self appendToProgressText:theString bold:theBold]; 
    [progressTextView.textStorage endEditing]; 
    [progressTextView didChangeText]; 
    [self performSelector:@selector(scrollProgressTextViewToEnd) withObject:nil afterDelay:0]; 
} 
progressTextView.textStoragetheStringを追加し、 progressTextViewを使用していません appendToProgressText

方法。

関連する問題