8
votes

Does anyone know of any class or lib that can implement autocompletion to an NSTextField?

I'am trying to get the standard autocmpletion to work but it is made as a synchronous api. I get my autocompletion words via an api call over the internet.

What have i done so far is:

- (void)controlTextDidChange:(NSNotification *)obj
{
    if([obj object] == self.searchField)
    {
        [self.spinner startAnimation:nil];
        [self.wordcompletionStore completeString:self.searchField.stringValue];

        if(self.doingAutocomplete)
            return;
        else
        {
            self.doingAutocomplete = YES;
            [[[obj userInfo] objectForKey:@"NSFieldEditor"] complete:nil];
        }
    }
}

When my store is done, i have a delegate that gets called:

- (void) completionStore:(WordcompletionStore *)store didFinishWithWords:(NSArray *)arrayOfWords
{
    [self.spinner stopAnimation:nil];
    self.completions = arrayOfWords;
    self.doingAutocomplete = NO;
}

The code that returns the completion list to the nstextfield is:

- (NSArray *)control:(NSControl *)control textView:(NSTextView *)textView completions:(NSArray *)words forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(NSInteger *)index
{
    *index = -1;
    return self.completions;
}

My problem is that this will always be 1 request behind and the completion list only shows on every 2nd char the user inputs.

I have tried searching google and SO like a mad man but i cant seem to find any solutions..

Any help is much appreciated.

2

2 Answers

9
votes

Instead of having the boolean property doingAutocomplete, make the property your control that made the request. Let's call it autoCompleteRequestor:

@property (strong) NSControl* autoCompleteRequestor;

So where you set your current property doingAutocomplete to YES, instead store a reference to your control.

- (void)controlTextDidChange:(NSNotification *)obj
{
    if([obj object] == self.searchField)
    {
        [self.spinner startAnimation:nil];
        [self.wordcompletionStore completeString:self.searchField.stringValue];

        if(self.autoCompleteRequestor)
            return;
        else
        {
            self.autoCompleteRequestor = [[obj userInfo] objectForKey:@"NSFieldEditor"];
        }
    }
}

Now when your web request is done, you can call complete: on your stored object.

- (void) completionStore:(WordcompletionStore *)store didFinishWithWords:(NSArray *)arrayOfWords
{
    [self.spinner stopAnimation:nil];
    self.completions = arrayOfWords;
    if (self.autoCompleteRequestor)
    {
       [self.autoCompleteRequestor complete:nil];
       self.autoCompleteRequestor = nil;
    }
}
-2
votes

NSTextView has the functionality of completing words of partial words.

Take a look at the documentation for this component. Maybe you can switch to this component in your application.