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;
}
我做了類似的事情,滾動是在下一個runloop迭代上執行的,如'[self performSelector:@selector(scrollProgressTextViewToEnd)withObject:nil afterDelay:0];'。 – Willeke
@Willeke第一次去,這似乎是工作!將這一天搞砸了,但請介意補充說,作爲答案,我可以給你信用? –
因此,在嘗試幾個小時之後,它似乎仍然有時不滾動。 =/ –