在NSSearchField中检测自动完成

时间:2018-11-08 16:46:52

标签: objective-c macos cocoa mapkit nssearchfield

我正在尝试在搜索栏中实施位置建议。我可以得到所有建议,但是当用户使用键盘Enter或单击鼠标选择完成时,我无法查明。

问题是用户需要按Enter键选择完成(dismiss完成菜单窗口),然后再次按Enter键以将其提交给最新用户。我希望避免再次按下Enter键。

“发送完整字符串”模式的自动补全功能已关闭,因此无法进行。

如何在NSSearchField上检测自动完成选择?还是如何通过“发送整个搜索字符串”来触发自动补全?

PS:可能会使用未记录的通知NSTextViewDidBeginDisplayingCompletions,NSTextViewDidEndDisplayingCompletions。

autocomplete nssearchfield

- (void)windowDidLoad {
    [super windowDidLoad];

    MKLocalSearchCompleter *searchCompleter = [[MKLocalSearchCompleter alloc] init];
    searchCompleter.filterType = MKSearchCompletionFilterTypeLocationsOnly;
    searchCompleter.delegate = self;
    [self setSearchCompleter:searchCompleter];

    [[NSNotificationCenter defaultCenter] addObserverForName:@"NSTextViewDidEndDisplayingCompletions" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
        self.displayingCompletions = YES;
    }];

    [[NSNotificationCenter defaultCenter] addObserverForName:@"NSTextViewDidEndDisplayingCompletions" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
        self.displayingCompletions = NO;
        if ([[self searchCompleter] isSearching] == NO) {
            [self search:nil];
        }
    }];
}

- (void)completerDidUpdateResults:(MKLocalSearchCompleter *)completer
{
    [self setSearchAutocompletions:[completer results]];
    [self displayAutocompletions];
}

- (void)completer:(MKLocalSearchCompleter *)completer didFailWithError:(NSError *)error
{
    if (error) {
        NSLog(@"%@",error);
    }
}

- (IBAction)autocompleteSearch:(NSSearchField *)sender
{
    if ([[sender stringValue] length] < 3) {
        return;
    }
    if (self.isDisplayingCompletions) {
        return;
    }
    NSString *searchString = [sender stringValue];
    [[self searchCompleter] cancel];
    [[self searchCompleter] setQueryFragment:searchString];
}



- (void)displayAutocompletions
{
    if (self.isSearching && !self.completePosting) {
        _completePosting = YES;
        [[[self window] fieldEditor:YES forObject:[self searchField]] complete:nil];
        _completePosting = NO;
    }
}

- (void)controlTextDidEndEditing:(NSNotification *)obj
{
    [self search:nil];
}

- (void)search:(id)sender
{
    NSString *searchString = [[self searchField] stringValue];
    if ([searchString length] <= 3) {
        return;
    }
    MKLocalSearchCompletion *completionToSearch;
    NSArray<MKLocalSearchCompletion *> *results = [[self searchCompleter] results];
    for (MKLocalSearchCompletion *completion in results) {
        if ([[completion title] isEqualToString:searchString]) {
            completionToSearch = completion;
            break;
        }
    }
//    MKCoordinateRegion boundingRegion = [[self mapView] region];
    MKLocalSearchRequest *request;
    if (completionToSearch) {
        request = [[MKLocalSearchRequest alloc] initWithCompletion:completionToSearch];
    } else {
        request = [[MKLocalSearchRequest alloc] init];
        [request setNaturalLanguageQuery:searchString];
    }
    //[request setRegion:boundingRegion];
    [[self localSearch] cancel];
    MKLocalSearch *localSearch = [[MKLocalSearch alloc] initWithRequest:request];
    [self setLocalSearch:localSearch];
    [localSearch startWithCompletionHandler:^(MKLocalSearchResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            NSLog(@"%@", error);
        } else {
            [[self mapView] setRegion:[response boundingRegion]];
            MKMapItem *item = [response.mapItems firstObject];
            [[self searchField] setStringValue:[item name]];
            MKPlacemark *placemark = [item placemark];

            if (placemark) {
                CLLocationCoordinate2D coordinate = placemark.coordinate;
                NSLog(@"%@", placemark);
            }
        }
    }];

}

#pragma mark NSControlTextEditingDelegate

- (NSArray *)control:(NSControl *)control textView:(NSTextView *)textView completions:(NSArray *)words forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(NSInteger *)index
{
    NSMutableArray *matches = [[NSMutableArray alloc] init];
    for (MKLocalSearchCompletion *completion in [self searchAutocompletions]) {
            [matches addObject:[completion title]];
    }
    *index = -1;
    return matches;
}

#pragma mark NSSearchFieldDelegate

- (void)searchFieldDidStartSearching:(NSSearchField *)sender
{
    _searching = YES;
}

- (void)searchFieldDidEndSearching:(NSSearchField *)sender
{
    _searching = NO;
}

0 个答案:

没有答案