How to deal with first responder and a NSPopover

2019-03-28 03:33发布

问题:

I’m trying to replicate the behaviour of the search field in iTunes, for looking up stock symbols and names. Specifically, as you start typing in the search field a popover appears with the filtered items. For the most part I have this working however what I can’t replicate is the way it handles first responder

I have my popover appear after three characters are entered. At this point the NSSearchField would lose first responder status and therefore I could no longer continue typing. The behaviour I would like is the ability to continue typing after the popover appears if scrolling through the items with the arrow keys, and then resume typing, you would continue from the last character in the Search field.

What I tried is subclassing NSTextView (use this as the custom field editor for the NSSearchField) and overriding

- (BOOL)resignFirstResponder 

By simply returning NO, I can continue typing once the popover appears, but obviously I can’t select any of the items in the popover. So i tried the following, which returns YES if the down arrow or a mousedown event occurs.

@interface SBCustomFieldEditor ()
{
    BOOL resignFirstRepond;
}
@end

@implementation SBCustomFieldEditor

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
        resignFirstRepond = NO;
    }
    return self;
}

- (BOOL)resignFirstResponder
{
    return resignFirstRepond;
}

- (void)keyDown:(NSEvent *)theEvent
{
    if ([theEvent keyCode] == 125) {
        resignFirstRepond = YES;
        [self resignFirstResponder];
    }
    [super keyDown:theEvent];
}

- (void)mouseDown:(NSEvent *)theEvent
{
    resignFirstRepond = YES;
    [self resignFirstResponder];
}

This works for the mousedown event, but not the keydown event, furthermore this doesn’t address the issue, when the user resumes typing.

Any suggestions?

回答1:

In the meantime I found an easy fix. Subclass your text view and implement - (BOOL)canBecomeKeyView. Always return NO there. It will be called only once when the popover is shown. You can work with the text view any time still.