我有一个显示我称之为“滚动日志”的NSTextView。新的AttributedString
几乎每秒都会被添加。我想做的是,如果字符串达到一定长度或一定数量的行,则从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 :(得分: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
将theString
添加到progressTextView.textStorage
,但不使用progressTextView
。