抑制NSTextField的文本完成下拉列表

时间:2011-08-12 13:35:42

标签: objective-c cocoa macos autocomplete nstextfield

我正在尝试使用completes == YES,没有按钮和numberOfVisibleItems == 0来创建NSComboBox的效果(例如,尝试在iTunes中填写相册或艺术家获取信息窗口。)

为了实现这一点,我正在使用NSTextField控件,该控件在-controlTextDidChange:上自动填充以调用-[NSTextField complete:],从而触发委托方法:

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

我已经正确地工作了,唯一的问题是下拉显示的副作用。我想压制它,但我还没有看到这样做的方法。我已经搜索了文档,Internet和Stack Overflow,但没有成功。

我更喜欢委托方法,但我愿意继承子类,如果这是唯一的方法。我瞄准Lion,如果它有帮助,所以解决方案不需要向后兼容。

1 个答案:

答案 0 :(得分:4)

要解决这个问题,我不得不在盒子外思考一下。我没有使用内置的自动完成机制,而是建立了自己的机制。这并不像我原先认为的那样艰难。我的-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;
}

更新:简化和更正的解决方案

它现在不会跟踪用户输入的最后一个字符串,而是检测用户何时删除。这可以直接而不是迂回的方式解决问题。