Подавление раскрывающегося списка завершения текста для NSTextField

Я пытаюсь создать эффект NSComboBox с completes == ДА, нет кнопки, и numberOfVisibleItems == 0 (например, попробуйте заполнить альбом или исполнителя в окне "Информация" в iTunes).

Для этого я использую элемент управления NSTextField, который автоматически завершает -controlTextDidChange: звонить -[NSTextField complete:], который вызывает метод делегата:

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

Я получил это работает правильно, единственная проблема заключается в побочном эффекте раскрывающегося списка. Я хотел бы подавить это, но я не видел способа сделать это. Я проверил документацию, Интернет и переполнение стека, но безуспешно.

Я бы предпочел метод делегата, но я открыт для подклассов, если это единственный способ. Я нацеливаюсь на Lion, если это поможет, поэтому решения не должны быть обратно совместимыми.

1 ответ

Решение

Чтобы решить эту проблему, мне пришлось немного нестандартно мыслить. Вместо того, чтобы использовать встроенный механизм автозаполнения, я построил свой собственный. Это было не так сложно, как я изначально предполагал. мой -controlTextDidChange: выглядит так:

- (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;
    }
}

А затем я реализовал еще один метод делегата, о котором раньше не знал (так сказать, недостающий фрагмент головоломки).

- (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;
}

Обновление: упрощенное и исправленное решение

Теперь он не отслеживает последнюю введенную пользователем строку, а определяет, когда пользователь удалил. Это решает проблему прямым, а не окольным путем.

Другие вопросы по тегам