Метод автозаполнения NSTextField - PullRequest
3 голосов
/ 19 июня 2011

У меня проблема с запуском complete: метода для NSTextfield.

на данный момент я могу создать отдельный массив имен из текстового поля, используя @distinctUnionOfObjects (отличный способ удалить дубликаты массива), и теперь я могу отправить автозаполнение для этого текстового поля, используя:
- (NSArray *)control:(NSControl *)control textView:(NSTextView *)textView completions:(NSArray *)words forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(NSInteger *)index

Но этот метод не является автоматическим, и мне нужно нажать кнопку ESC , чтобы выдвинуть предложение автозаполнения для текстового поля во время ввода данных.

Я искал здесь и нашел несколько примеров, которые не имеют смысла для меня.

Краткий вопрос: Есть ли какой-нибудь метод, использующий NSTexfields делегатов вроде controlDidChanged или что-то в этом роде, чтобы сделать это проще и понятнее?

Я просто путаю использование метода complete: для nstextview.

Ответы [ 2 ]

7 голосов
/ 29 января 2012

Я не рекомендую копировать всю строку.Это было бы хорошо для вашего случая, но если вы используете автозаполнение для большого текстового файла, то у вас будут все виды проблем с производительностью и памятью.Вы можете просто отслеживать, находитесь ли вы в середине обновления.Если у вас есть несколько текстовых представлений, вы можете создать словарь для переменных isCompleting.

- (void) controlTextDidChange: (NSNotification *)note {
    NSTextView * fieldEditor = [[note userInfo] objectForKey:@"NSFieldEditor"];

    if (!isCompleting) {
        isCompleting = YES;
        [fieldEditor complete:nil];
        isCompleting = NO;
    }
}
4 голосов
/ 19 июня 2011

Когда ваш делегат текстового поля получает controlTextDidChange:, вы можете вызвать complete: в Редакторе полей . Этот метод вызывается при нажатии клавиши ESC или F5.

- (void) controlTextDidChange: (NSNotification *)note {
    NSTextView * fieldEditor = [[note userInfo] objectForKey:@"NSFieldEditor"];

    [fieldEditor complete:nil];
}

Сложность в том, что при навигации по меню завершения будет происходить повторная отправка сообщений controlTextDidChange: (хотя и без изменения фактической строки), что создаст бесконечный цикл. Вам понадобится какой-нибудь флаг, чтобы не вызывать complete:, когда вы уже находитесь в середине завершения. Например, вы можете отслеживать последние изменения, внесенные пользователем в строку, и сравнивать их с текущим значением редактора полей; если нет изменений, инициированных пользователем, не вызывать завершение:

BOOL textDidNotChange = [lastTypedString isEqualToString:[fieldEditor string]];

if( textDidNotChange ){
    return;
}
else {
    lastTypedString = [[fieldEditor string] copy];
    [fieldEditor complete];
}
...