Подавление раскрывающегося списка завершения текста для 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;
}
Обновление: упрощенное и исправленное решение
Теперь он не отслеживает последнюю введенную пользователем строку, а определяет, когда пользователь удалил. Это решает проблему прямым, а не окольным путем.