NSTextField autocompletion delegate method not called
Asked Answered
O

1

8

I implemented the following delegate method for NSTextField to add autocompletion support:

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

The issue is that this method never gets called. I can verify that the delegate of the NSTextField is set properly because the other delegate methods function as they should.

Orient answered 2/4, 2011 at 19:6 Comment(0)
V
7

You'll need to get complete: called on the text field's field editor at some point. That's what triggers the completions menu, but it doesn't get called automatically. If you don't have F5 bound to anything, try typing in your field and hit that. Completion should trigger then; Option-Esc may also work.

If you want auto completion, it takes some work. You could start with something like this:

- (void)controlTextDidChange:(NSNotification *)note {
    if( amDoingAutoComplete ){
        return;
    } else {
        amDoingAutoComplete = YES;
        [[[note userInfo] objectForKey:@"NSFieldEditor"] complete:nil];
    }
}

Some kind of flag is necessary because triggering completion will make NSControlTextDidChangeNotification be posted again, which causes this to be called, triggering completion, which changes the control text, which...

Obviously, you'll need to unset the flag at some point. This will depend on how you want to handle the user's interaction with autocompletion -- is there likely to only be one completion for a given start string, or will the user need to keep typing to narrow down possibilities (in which case you'll need to trigger autocompletion again)?

A simple flag might not quite do it, either; it seems that although the notification is re-posted, the field editor's string won't have changed -- it will only change in response to direct keyboard input. In my implementation of autocomplete, I found that I had to keep a copy of the "last typed string" and compare that each time to the field editor's contents.

Voracity answered 2/4, 2011 at 20:3 Comment(2)
How did you account for backspacing? Using this basic logic, the autocomplete code fires every time backspace is hit, thus nullifying its effect.Hanky
You can catch backspaces in control:textView:doCommandBySelector: and do something different if necessary. (The control I'm using this on is a field for entering a file system path, so in my case, there is no possibility of the user needing to enter something not in the completions list.)Voracity

© 2022 - 2024 — McMap. All rights reserved.