anがレイヤーバック( )NSTextView
のサブビューである場合、スペルミスのある単語の波状の赤い下線は表示されません。これを再現するために必要なのは、空のCocoaプロジェクトを作成し、ペン先を開き、ウィンドウにドラッグして、ウィンドウのコンテンツビューを切り替えてレイヤーを作成することだけです。ブーム-赤い下線はもうありません。NSView
-wantsLayer == YES
NSTextView
私はいくつかの検索を行いましたが、これは既知の状況のようであり、10.5から当てはまります。しかし、私が見つけられないのは、その回避策です。NSTextView
レイヤーバックビューにあるときに下線をレンダリングする方法はありませんか?
をオーバーライドし、レイアウトマネージャーを使用して、スペルミスを示す適切な一時属性が設定された適切な四角形を見つけて、自分で赤い波線を描くことを想像できますが、それはもちろん完全なハックNSTextView
です。drawRect:
私はまた、Appleが10.7でこれを修正することを想像することができます(おそらく)そして突然私のアプリは二重の下線か何かを持つでしょう。
[更新]私の回避策
私の現在の回避策は、nptacekの言及されたスペルチェックデリゲートメソッドに触発され、以前は気づかなかったパスを深く掘り下げるように促されたので、その答えを受け入れますが、後世のために行ったことを投稿します。討論。
10.6.5を実行しています。NSClipViewのカスタムサブクラスのドキュメントビューであるNSTextViewのサブクラスがあります。これは、レイヤーがオンになっているウィンドウのcontentViewのサブビューです。これで遊んでいると、最終的にすべてのカスタマイズがコメントアウトされましたが、それでもスペルチェックが正しく機能していませんでした。
私は、2つの明確な問題が何であるかを特定しました。
#1は、NSTextViewがレイヤーに裏打ちされたビューでホストされている場合、スペルミスの下線をわざわざ描画することさえないということです。(Googleの検索に基づいて、10.5日間に下線が引かれた時期があったかもしれないが、正しい場所にはなかった可能性があることを収集しました。そのため、Appleは10.6でその問題を回避するために、それらを完全に無効にした可能性があります。わかりません。 。また、私が物を配置する方法などの副作用があり、私の場合はまったく表示されない可能性があります。現在は不明です。)
#2NSTextViewがこのレイヤー関連の状況にある場合、-isContinuousSpellCheckingEnabledがYESに設定されている場合でも、入力中にテキストのスペルが間違っていると正しくマークされていないように見えます。いくつかのスペルチェックデリゲートメソッドを実装し、NSTextViewが変更に関するメッセージを送信するのを見て、テキスト範囲をスペルミスとして設定するように通知することはありませんでした-テキストエディット(および他のテキストビューで赤い下線が表示される明らかにスペルミスの単語がある場合でも)他のアプリで)。また、NSTextViewの-handleTextCheckingResults:forRange:types:options:orthography:wordCount:をオーバーライドして、何が表示されているかを確認しましたが、同じものが表示されました。NSTextViewがカーソルの下の単語をスペルミスがないようにアクティブに設定していて、ユーザーがスペースを入力したり、スペースから離れたりしたときに、そうではなかったようです。tスペルミスがないか再確認します。しかし、私は完全にはわかりません。
さて、#1を回避するために、カスタムNSTextViewサブクラスの-drawRect:をオーバーライドして次のようにします。
- (void)drawRect:(NSRect)rect
{
[super drawRect:rect];
[self drawFakeSpellingUnderlinesInRect:rect];
}
次に、-drawFakeSpellingUnderlinesInRect:を実装して、layoutManagerを使用して、一時的な属性としてNSSpellingStateAttributeNameを含むテキスト範囲を取得し、標準のOSXスペルミスのドットパターンにかなり近いドットパターンをレンダリングしました。
- (void)drawFakeSpellingUnderlinesInRect:(NSRect)rect
{
CGFloat lineDash[2] = {0.75, 3.25};
NSBezierPath *underlinePath = [NSBezierPath bezierPath];
[underlinePath setLineDash:lineDash count:2 phase:0];
[underlinePath setLineWidth:2];
[underlinePath setLineCapStyle:NSRoundLineCapStyle];
NSLayoutManager *layout = [self layoutManager];
NSRange checkRange = NSMakeRange(0,[[self string] length]);
while (checkRange.length > 0) {
NSRange effectiveRange = NSMakeRange(checkRange.location,0);
id spellingValue = [layout temporaryAttribute:NSSpellingStateAttributeName atCharacterIndex:checkRange.location longestEffectiveRange:&effectiveRange inRange:checkRange];
if (spellingValue) {
const NSInteger spellingFlag = [spellingValue intValue];
if ((spellingFlag & NSSpellingStateSpellingFlag) == NSSpellingStateSpellingFlag) {
NSUInteger count = 0;
const NSRectArray rects = [layout rectArrayForCharacterRange:effectiveRange withinSelectedCharacterRange:NSMakeRange(NSNotFound,0) inTextContainer:[self textContainer] rectCount:&count];
for (NSUInteger i=0; i<count; i++) {
if (NSIntersectsRect(rects[i], rect)) {
[underlinePath moveToPoint:NSMakePoint(rects[i].origin.x, rects[i].origin.y+rects[i].size.height-1.5)];
[underlinePath relativeLineToPoint:NSMakePoint(rects[i].size.width,0)];
}
}
}
}
checkRange.location = NSMaxRange(effectiveRange);
checkRange.length = [[self string] length] - checkRange.location;
}
[[NSColor redColor] setStroke];
[underlinePath stroke];
}
したがって、これを行った後、赤い下線が表示されますが、入力してもスペルの状態が更新されないようです。この問題を回避するために、NSTextViewサブクラスに次の邪悪なハックを実装しました。
- (void)setNeedsFakeSpellCheck
{
if ([self isContinuousSpellCheckingEnabled]) {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(forcedSpellCheck) object:nil];
[self performSelector:@selector(forcedSpellCheck) withObject:nil afterDelay:0.5];
}
}
- (void)didChangeText
{
[super didChangeText];
[self setNeedsFakeSpellCheck];
}
- (void)updateInsertionPointStateAndRestartTimer:(BOOL)flag
{
[super updateInsertionPointStateAndRestartTimer:flag];
[self setNeedsFakeSpellCheck];
}
- (void)forcedSpellCheck
{
[self checkTextInRange:NSMakeRange(0,[[self string] length]) types:[self enabledTextCheckingTypes] options:nil];
}
これは、実際の予想されるOSXの動作とまったく同じようには機能しませんが、かなり近いものであり、今のところ作業は完了しています。うまくいけば、これは他の誰かに役立つか、もっと良いことに、誰かがここに来て、私が信じられないほど単純なものが欠けていると私に言い、それを修正する方法を説明します。:)