2011-08-12 1 views
3

NSComboBoxの効果をcompletes == YES、ボタンなし、numberOfVisibleItems == 0で作成しようとしています(例:iTunesの情報ウィンドウを開く)。NSTextFieldのテキスト補完のドロップダウンを抑制する

これを達成するために、私は、デリゲートメソッドトリガー-[NSTextField complete:]、呼び出すために-controlTextDidChange:に自動的に補完NSTextFieldコントロールを使用しています:私はあることこの正常に動作し、唯一の問題を得ている

- (NSArray *)control:(NSControl *)control 
      textView:(NSTextView *)textView 
     completions:(NSArray *)words 
forPartialWordRange:(NSRange)charRange 
indexOfSelectedItem:(NSInteger *)index; 

をドロップダウンの副作用が表示されます。私はそれを抑制したいが、私はこれを行う方法を見ていない。ドキュメント、インターネット、スタックオーバーフローを精査しましたが、成功しませんでした。

私はデリゲートメソッドが好きですが、それが唯一の方法であれば、サブクラス化することができます。私はライオンをターゲットにしています。そのために役立つので、ソリューションは下位互換性が必要ではありません。

答えて

4

これを解決するには、箱の外で少し考えなければなりませんでした。組み込みのオートコンプリートメカニズムを使用する代わりに、私は自分自身を構築しました。私が当初想定していたほど厳しいものではありませんでした。

- (void)controlTextDidChange:(NSNotification *)note { 
    // Without using the isAutoCompleting flag, a loop would result, and the 
    // behavior gets unpredictable 
    if (!isAutoCompleting) { 
     isAutoCompleting = YES; 

     // Don't complete on a delete 
     if (userDeleted) { 
      userDeleted = NO; 
     } else { 
      NSTextField *control = [note object]; 
      NSString *fieldName = [self fieldNameForTag:[control tag]]; 
      NSTextView *textView = [[note userInfo] objectForKey:@"NSFieldEditor"]; 

      NSString *typedText = [[textView.string copy] autorelease]; 
      NSArray *completions = [self comboBoxValuesForField:fieldName 
                 andPrefix:typedText]; 

      if (completions.count >= 1) { 
       NSString *completion = [completions objectAtIndex:0]; 

       NSRange difference = NSMakeRange(
             typedText.length, 
             completion.length - typedText.length); 
       textView.string = completion; 
       [textView setSelectedRange:difference 
            affinity:NSSelectionAffinityUpstream 
          stillSelecting:NO]; 
      } 
     } 

     isAutoCompleting = NO; 
    } 
} 

そして私は私が(いわば、パズルの欠けている部分)の以前に認識していなかった別のデリゲートメソッドを実装し:私-controlTextDidChange:はそうのように見えます。

- (BOOL)control:(NSControl *)control 
     textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector { 
    // Detect if the user deleted text 
    if (commandSelector == @selector(deleteBackward:) 
     || commandSelector == @selector(deleteForward:)) { 
     userDeleted = YES; 
    } 

    return NO; 
} 

更新:簡体字および修正ソリューション

今では、ユーザーが削除したときの代わりに検出し、ユーザーが入力した最後の文字列を追跡することはありません。これは、ラウンドアバウトではなく直接的な問題を解決します。

+0

userDeletedとisAutoCompletingには関連性がありません。これらの2つを1つのプロパティにマージすることで、コードをさらに単純化することができます。 – lhunath

+0

それは当てはまりません。ユーザーが削除キーを押すと、このコードはオートコンプリートを提供しません。これはiTunesが動作するのと同じ方法です。 'isAutoCompleting'は、コントロールのテキストが変化している間、関数へのリエントリーを禁止することによって、無限ループを防ぎます。 – Dov

+0

私が言っていることは、どちらも同じ目標を達成することです。isAutoCompletingがYESの場合、完了しません。 userDeletedがYESの場合も、完了しません。たとえば、isAutoCompletingまたはuserDeletedをYESに設定し、コードとチェックが少なくても同じ効果が得られる場合は、単一の変数「inhibitCompletion」を使用してYESに設定することもできます。 – lhunath

関連する問題