2016-09-20 62 views
0

我有一個NSTextView顯示我將稱之爲「滾動日誌」。幾乎每秒都會添加新的AttributedString。我想要做的是從NSTextView開始截斷,如果字符串已經達到了一定的長度或一定數量的行。這是爲了使顯示的日誌不佔用大量內存。限制自動滾動的文本長度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

我做了類似的事情,滾動是在下一個runloop迭代上執行的,如'[self performSelector:@selector(scrollProgressTextViewToEnd)withObject:nil afterDelay:0];'。 – 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]; 
} 

方法appendToProgressText增加theStringprogressTextView.textStorage,並且不使用progressTextView