私はそれを確実に動作させることができなかったので、私は、しばらくの間、このをいじってきました。私は最終的に私のコードが動作したので、私は返信として投稿したいと思います。
私のソリューションでは、出力がビューに追加されている間に手動でスクロールすることができます。 NSTextViewの絶対下部までスクロールすると、自動的にスクロールが再開されます(有効になっている場合)。まず
この必要なだけ...
FSScrollToBottomExtensions.h #IMPORTするカテゴリ:
@interface NSView (FSScrollToBottomExtensions)
- (float)distanceToBottom;
- (BOOL)isAtBottom;
- (void)scrollToBottom;
@end
がFSScrollToBottomExtensions.m:
@implementation NSView (FSScrollToBottomExtensions)
- (float)distanceToBottom
{
NSRect visRect;
NSRect boundsRect;
visRect = [self visibleRect];
boundsRect = [self bounds];
return(NSMaxY(visRect) - NSMaxY(boundsRect));
}
// Apple's suggestion did not work for me.
- (BOOL)isAtBottom
{
return([self distanceToBottom] == 0.0);
}
// The scrollToBottom method provided by Apple seems unreliable, so I wrote this one
- (void)scrollToBottom
{
NSPoint pt;
id scrollView;
id clipView;
pt.x = 0;
pt.y = 100000000000.0;
scrollView = [self enclosingScrollView];
clipView = [scrollView contentView];
pt = [clipView constrainScrollPoint:pt];
[clipView scrollToPoint:pt];
[scrollView reflectScrolledClipView:clipView];
}
@end
を... "自分で作成することOutputView "(NSTextViewのサブクラス):
FSOutputView.h:
@interface FSOutputView : NSTextView
{
BOOL scrollToBottomPending;
}
FSOutputView.m:
@implementation FSOutputView
- (id)setup
{
...
return(self);
}
- (id)initWithCoder:(NSCoder *)aCoder
{
return([[super initWithCoder:aCoder] setup]);
}
- (id)initWithFrame:(NSRect)aFrame textContainer:(NSTextContainer *)aTextContainer
{
return([[super initWithFrame:aFrame textContainer:aTextContainer] setup]);
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (void)awakeFromNib
{
NSNotificationCenter *notificationCenter;
NSView *view;
// viewBoundsDidChange catches scrolling that happens when the caret
// moves, and scrolling caused by pressing the scrollbar arrows.
view = [self superview];
[notificationCenter addObserver:self
selector:@selector(viewBoundsDidChangeNotification:)
name:NSViewBoundsDidChangeNotification object:view];
[view setPostsBoundsChangedNotifications:YES];
// viewFrameDidChange catches scrolling that happens because text
// is inserted or deleted.
// it also catches situations, where window resizing causes changes.
[notificationCenter addObserver:self
selector:@selector(viewFrameDidChangeNotification:)
name:NSViewFrameDidChangeNotification object:self];
[self setPostsFrameChangedNotifications:YES];
}
- (void)handleScrollToBottom
{
if(scrollToBottomPending)
{
scrollToBottomPending = NO;
[self scrollToBottom];
}
}
- (void)viewBoundsDidChangeNotification:(NSNotification *)aNotification
{
[self handleScrollToBottom];
}
- (void)viewFrameDidChangeNotification:(NSNotification *)aNotification
{
[self handleScrollToBottom];
}
- (void)outputAttributedString:(NSAttributedString *)aAttributedString
flags:(int)aFlags
{
NSRange range;
BOOL wasAtBottom;
if(aAttributedString)
{
wasAtBottom = [self isAtBottom];
range = [self selectedRange];
if(aFlags & FSAppendString)
{
range = NSMakeRange([[self textStorage] length], 0);
}
if([self shouldChangeTextInRange:range
replacementString:[aAttributedString string]])
{
[[self textStorage] beginEditing];
[[self textStorage] replaceCharactersInRange:range
withAttributedString:aAttributedString];
[[self textStorage] endEditing];
}
range.location += [aAttributedString length];
range.length = 0;
if(!(aFlags & FSAppendString))
{
[self setSelectedRange:range];
}
if(wasAtBottom || (aFlags & FSForceScroll))
{
scrollToBottomPending = YES;
}
}
}
@end
...あなたは(私はそれを取り除いてきました)このクラスにさらにいくつかの便利なメソッドを追加することができ、フォーマットされた文字列を出力することができますように。
- (void)outputString:(NSString *)aFormatString arguments:(va_list)aArguments attributeKey:(NSString *)aKey flags:(int)aFlags
{
NSMutableAttributedString *str;
str = [... generate attributed string from parameters ...];
[self outputAttributedString:str flags:aFlags];
}
- (void)outputLineWithFormat:(NSString *)aFormatString, ...
{
va_list args;
va_start(args, aFormatString);
[self outputString:aFormatString arguments:args attributeKey:NULL flags:FSAddNewLine];
va_end(args);
}
[OK]を、私は「スマート」BOOLスクロールの必要性が表示されません。まず、BOOLスクロールの式では、演算子は==の代わりに!=にする必要があります。意味があり、!=私のために働くが、==は機能しません。次に、改行で終わる1行のテキストを追加すると、改行が表示されることがあり、時には改行がないこともあります。なぜ私たちが「テキストビューの内容の終わりまでスクロールしたくない」のではないのか分かりません。それが私たちが望むものです。すべての場合。私はif(スクロール)行を削除し、うまく動作します。たぶん我々は反対側のケースでテストしています:)) –
「[self.textView scrollRangeToVisible:NSMakeRange(self.textView.string.length、0)]」を使用するように注意してください。これは実際にはNSTextViewのレイアウトに応じて、実際には下にスクロールしないことがあります。)NSTextViewの高さがテキスト行の高さで均等に割り切れない場合、テキストの下の行を部分的に切り捨てる可能性があります(この場合、スマートスクロールは機能しません)。 : "self.textView.scrollToVisible(NSRect(x:0、y:self.textView.frame.height-1、width:self.textView.frame.width、height:1))"。 – pauln
また、私はスクロールフラグを微調整していることが分かりました。ちょっとしたスラックがありますので、正確な一番下にある必要はありません(Swiftの例): 'let scroll = abs(self.logTextView.visibleRect。 maxY - self.logTextView.bounds.maxY)
pauln